Git is a distributed revision control system. Explaining git itself is beyond the scope of this document; instead the aim is to briefly explain the git-svn extension and how to use it with Native Client. Git-svn is a git extension that uses a local git repository backed by a central Subversion server. The commits in Subversion appear in the git repository as a remote branch, and you can fork your own branches off of svn HEAD, or any other commit in your repository. The git-svn extension fetches commits from svn and checks them into git, and when you are ready to commit to svn, it takes your git commits and checks them into the remote Subversion server. A tool called git-cl (part of the depot_tools) manages code review, try jobs, and the other tasks you would use gcl for in a Subversion environment.
Native Client uses Subversion as its centralized source control system. Why would we want to pile git on top of that? There are 2 reasons. First, in order to have multiple CLs in flight at once, using Subversion requires you have multiple checkouts of the source and all the deps, each of which is dedicated to a single set of changes. Conversely git's model uses a single directory and switches back and forth between different branches (or commits in a branch), modifying the files in the working directory. You might or might not think this is an advantage; that's largely a matter of taste. However the real benefit is that when you use git, you can commit to your local branches as often as you want, for whatever reason you want; to save your progress partway through a task, to try different approaches, or to facilitate easy switching between different CLs. The setup described here is analogous to the preferred way to use git with Chromium, described at http://code.google.com/p/chromium/wiki/UsingNewGit
Setup from scratch
sudo apt-get install git-svn Create a directory to hold Native Client and all its deps (We'll call it $NACL_DIR) and cd into it. cd $NACL_DIR[OPTIONAL] This svn command may help you avoid incomprehensible password prompts: svn ls svn://svn.chromium.org/native_client/trunk/src/native_clientSetup your .gclient file, using git-style DEPS: gclient config https://chromium.googlesource.com/native_client/src/native_client.git --git-depsgclient sync -j16You'll notice that all the DEPS checkouts tell you about big long hex numbers (git commit IDs) instead of short decimal numbers (svn revision numbers). This is the key difference from the old regime: all the DEPS checkouts are git checkouts, rather than svn checkouts. (You'll also notice that this first "gclient sync" run takes a while--it's getting the entire history of each DEPS repository, not just the current checkouts. Thereafter, the incremental updates are usually much faster than with svn.) This gives you a setup very analogous to the all-svn setup you get from using plain gclient. Notably, your main native_client checkout is "managed" by gclient. This means that "gclient sync" will update your git checkout. (See below for how to get around this if you prefer to update native_client yourself). If you don't need to commit, you are done. You can use a pure git checkout, and keep it up to date by running "gclient sync" from $NACL_DIR If you do need to commit, you need to setup git-svn. cd native_clientgit svn init --prefix=origin/ -T trunk/src/native_client svn://svn.chromium.org/native_clientgit config svn-remote.svn.fetch trunk/src/native_client:refs/remotes/origin/mastergit svn fetchgit cl config # just hit return at all the promptsNow you have a native_client directory controlled by git-svn. The origin/master branch mirrors SVN trunk, and your local master branch tracks the master branch from the origin remote. You should not make local commits to your master branch, or gclient may complain about not being able to fast-forward the merge (and then eat that complaint, not showing you the text until you hit "enter" on what looks like a hung update). Your workflow might be like the following:
Update your master branch cd native_clientgit checkout mastergclient syncThe 'gclient sync' command will pull down the changes on origin/master and merge them into your local checked-out master branch. Create a new branch for a new CL
git checkout -b my_feature(This is equivalent to git branch my_feature; git checkout my_feature)
Hack away, committing to git whenever you like
emacs $filegit commit -a (roughly equivalent to git add $file; git commit)emacs $filegit commit -a./scons $testsI like to at least have a commit for every time I run a test (or try job) that takes sufficiently long that I won't sit and wait for it. That way when I come back and look at the results, I'm sure to have a snapshot of my code that was tested, even if I make new edits while the test is running. Send a try job git tryWatch out! The command for sending try jobs is 'git try', not 'git cl try'.
Send out for code review
git cl uploadThis creates a new CL and associates it with the current branch (all commits on this branch are now assumed to be part of this CL). It then uploads it to the code review server. git cl upload also supports the -m option for the patch message, -r for reviewers, --cc for extra people to CC in the email, and a few others.
Wait for the review to come back. In the meantime, you can switch to another branch and work on something else
git checkout mastergit checkout -b my_next_featureThat mean reviewer wanted changes!
Edit based on results of review, then re-upload for more review
git checkout my_featureemacs $filegit cl uploadGot LGTM! We are almost ready to commit to SVN. However, while you were waiting, there were other commits to nacl SVN, so we need to rebase my_feature against the new HEAD and make sure everything still works. First, update the local master: git checkout mastergclient syncThen, rebase your local changes off the new master: git checkout my_featuregit rebase masterTest, try and update as needed: ./scons <tests>git tryEverything works! Commit to SVN:
git cl dcommitgit cl dcommit squashes all the changes you made on your branch into a single diff and commits them to svn in a single commit. Now you can update your local master again* (to include the change you just committed) and start a new branch for your next CL.
git checkout mastergclient syncgit checkout -b my_even_newer_feature(you may have to wait a few minutes for the change to propagate from SVN trunk to git master; see below) If you have a CL already in flight (especially one that was branched off of your previous feature branch rather than master), you will probably want to rebase it against master now. After you have updated your master branch as above, git checkout my_next_featuregit rebase masterManaging your own native_client checkout You may not want gclient to mess with your main native_client checkout. You can prevent this, making gclient only keep your DEPS up to date (based on the content of the currently checked-out native_client/DEPS file). Then you are responsible for updating native_client itself. To get this behavior do the following in the $NACL_DIR directory (i.e. the directory above native_client) gclient config http://chromium.googlesource.com/native_client/src/native_client.git --git-deps --unmanagedOr equivalently, edit $NACL_DIR/.gclient and change
"managed" : True, to "managed" : False, In the above workflow, everywhere it says 'gclient sync', you can do 'git pull' to update your native_client directory, followed by 'gclient sync' to update the DEPS based on the native_client/DEPS file you just checked out. Git mirroring and DEPS One final note about the mirroring: how this works is that the infrastructure folks have a cron job that runs every few minutes (I think it may be every 3 minutes) to update the various git mirrors from the svn repositories. If the DEPS file changes, then it regenerates .DEPS.git and does an automatic svn commit of the new .DEPS.git file. (A git-based gclient checkout looks at .DEPS.git and ignores DEPS.) So when you do a commit, you may have to wait a few minutes before you can see it in a git update. Other notes
|
