If you're new to Git but experienced with Subversion, we recommend following the Git-SVN Crash Course. This guide should help you understand how Git differs from Subversion and how to get up to speed the fastest.
For Windows (non-Cygwin users), just running gclient will download and setup everything else you need (including a partial install of msysgit):
For Cygwin/Mac/Linux users, you'll need to manually install:
Now tell git about yourself.
git config --global user.name "My Name"
If you want to use SVN (optional, only do this if you know you need it), ensure that you have a SVN account and that your login credentials are registered locally via:
svn ls svn://svn.chromium.org/chrome
Password is at https://chromium-access.appspot.com/.
When you first run this, you will be prompted for your credentials, which should then be stored locally. On second run these should automatically log you in, without prompting for credentials, otherwise, make sure "store-passwords" is not explicitly set to "no" in ~/.subversion/servers and ~/.subversion/config.
We will use the fetch tool included in depot_tools to check out Chromium, including all dependencies. This will create a new folder in your current working directory named src.
If you are Not a Committer you will need to add --nosvn=True argument to fetch, as in
fetch --nohooks chromium # 'chromium' may alternatively be one of blink, android, ios, see below. cd src git checkout master # if you are building for Linux only: ./build/install-build-deps.sh # if you are building for Android: ./build/install-build-deps-android.sh
Alternatives to 'fetch chromium' are:
fetch chromium # Blink from DEPS (most recent roll) - if you're not working on Blink itself
fetch chromium and fetch blink both fetch both Chromium and Blink, but the two commands fetch different versions of Blink: fetching chromium will get a dated Blink (most recent roll to Chromium), and is sufficient and easier if only working on Chromium, while fetching blink will instead get the latest Blink (ToT), and is useful if working on Blink.
In other words, fetch X if you want to work on X.
Post initial checkout, you should be able to switch between these via sync-webkit-git.py but better tooling is being worked on. If you wish to later add android to an existing chromium tree, sync-webkit-git.py will not help. It may be better to make a separate top level directory and have a parallel tree. While the projects can live happily in the same tree, we don't have tools yet to help you configure the tree for both.
If you're building Chrome for:
If you'd like to only sync to the last known good revision (lkgr), you can add a safe sync URL like so at the bottom of your solution (by editing the .gclient file in your checkout directory):
NOTE: Because of technical limitations you can only add a safesync_url after you've done your initial sync until this bug is fixed.
NOTE: If you use lkgr, gclient sync will ignore svn revisions you want to sync to using the -r or -H arguments. You need to comment out lkgr from your .gclient first.
NOTE: If you use lkgr when running gclient sync, note that rebasing a branch and sticking with lkgr can be a little tricky. Instead of rebasing on origin/master, rebase on origin/lkgr.
NOTE: If you change to lkgr with any open branches, they will get confused and have merge conflicts. If you must change while branches are open, it is a good idea to move all your changes using git cherry-pick to fresh branches based off of the lkgr version of master.
Update with git pull followed by gclient sync, as follows:
Alternatively (does git-merge instead of git-rebase):
Formally the above is "unmanaged mode". One can instead use "Managed mode" and just type gclient sync, but this is NOT RECOMMENDED. See "Managed mode" below; that mode automates the pulling, but has confusing behavior and is deprecated.
If developing Blink and Blink repo is also unmanaged (as described below), you'll need to pull Blink as well, as follows:
cd "$CHROMIUM_DIR" && git pull origin master
To speed up updating, using more jobs, for example --jobs=16:
With git you should make all your changes in a local branch. Once your change is committed, you can delete this branch.
Create a local branch named "mywork" and make changes to it.
Commit your change locally (this doesn't commit your change to the SVN or Git server)
git commit -a -v
If you added new files, you should tell git so by running git add <files> before committing.
Upload your change for review
git cl upload
Send a try job
git cl try
See Contributing code for more detailed git instructions, including how to update your CL when you get review comments.
There's a short tutorial that might be helpful to try before your first change: C++ in Chromium 101.
The preferred way to commit changes is by using the commit queue. If this is not an option, you can commit directly from your git checkout (
If you are a multitasker or want to build chromium for different targets without clobbering each other, then perhaps you'll like the gclient-new-workdir.py script located in depot_tools. The script works by creating a new working directory with symlinks pointing to the git database(s) found in your original chromium checkout. You can have as many working directories as you want without the overhead and hassle of cloning chromium multiple times.
gclient-new-workdir.py /path/to/original/chromium chromium2
(Please contact firstname.lastname@example.org if you have any problems with these instructions.)
This currently only describes working with branches of src.git. Support for working with branches of submodules is pending.
A few things to double-check before you start:
Now configure git-svn for the branch you want to work on and checkout the sources.
# Make sure you are in 'src'.
NOTE: If you are not a committer, you need to reference the public, read-only svn repository in the above commands, like:
git config --replace-all svn-remote.svn_$BRANCH.url http://src.chromium.org/chrome # You also need to convince git-svn that the commits on http://src.chromium.org/chrome are the same as those on svn://svn.chromium.org/chrome git config --replace-all svn-remote.svn_$BRANCH.rewriteRoot "svn://svn.chromium.org/chrome" git config --replace-all svn-remote.svn_$BRANCH.rewriteUUID "0039d316-1c4b-4281-b951-d872f2087c98"
From there, git cl commits to the right branch magically! Edit files, 'git commit', and 'git cl upload' as normal. The CL should show an "SVN Base" referencing the branch you are working on, like:
SVN Base: svn://svn.chromium.org/chrome/branches/1453/src
To get back to the trunk:
# Make sure you are in 'src'.
Also, if you need to merge changes to DEPS, see the internal ChromeReleaseBranches?? wiki page for some notes.
The above flow will get you a tree that you can commit from, but it won't compile properly because the submodules won't be synced to the right revision. If you have to test out a difficult cherry-pick that required manual editing to resolve conflicts, you can create a compilable (but not committable-from) tree synced to the latest release branch with the following:
Enumerate your local branches:
Switching from one branch to another: Example: Switching from branch 'mywork' to branch 'master.
We normally do our feature work in branches to keep changes isolated from each other. There are several different workflows that people use.
git checkout -b new_branch origin/master
git checkout -b new_branch master
If you have dependent changes, a very productive workflow is to have a branch off a branch. Notably, this means that your patch sets (in Rietveld) will show the separate changes, and be easy to review, rather than showing the merged changes (including irrelevant changes), and means you can commit downstream CLs without having to rebase them after the upstream has landed. Do this as follows:
If you update the upstream branch, you can rebase the downstream branch on this, but do not amend the original commit. If you amend the original commit, rebasing will have merge conflicts, which will be very tedious to resolve. Instead, make a new commit in the first branch, and rebase the second branch from it. (You can squash the first branch later if you'd like, but only after rebasing all dependent branches).
For making changes to the base branch and rebasing, do as follows:
Lastly, when an upstream branch has landed, and you've rebased it so it agrees with master, you can set the downstream branch's upstream branch to be master, which means you can now forget about the earlier branch:
A common variant of "branch off a branch" is splitting up a large CL into pieces. Given a local branch
One way to do this is to split off
This can be done manually, particularly if the files don't overlap, by making a new branch
However, this can be done more cleanly via git. The main points are
You generally want to delete local branches after the changes have been committed to master. It is safest to that your work has, in fact, been committed before deleting it.
Remember that you can always apply a CL that has been posted via:
git checkout -b myworkfrompatch
...so as long as your CL has been posted, you can easily recover your work. Otherwise, you'll need to dig through the git repository, so be careful.
Simply, if master (remote or local) is up-to-date and your branch has been rebased, git branch -d will delete the branch. If not, it will refuse; to force deletion, use git branch -D. So make sure master is up-to-date, rebase branch, and then try deleting (optionally check manually before).
Beware that if your local branch has many revisions (instead of always amending a single revision), rebasing to master may fail, since it will try to apply the patches incrementally. You can avoid this by squashing your local revisions into a single revision (see 6.4 Git Tools - Rewriting History, or more simply squashing commits with rebase). This may be more trouble than it's worth, but it's the safest way.
To check that the branch has been committed upstream (using remote repository - RECOMMENDED):
git checkout mywork
If there are no differences, delete the branch:
git checkout origin/master
Alternatively, using local repository (NOT RECOMMENDED):
Update local master from remote repository:
Rebase your branch:
git checkout mywork
git diff --stat master
If there are no differences, delete the branch:
git checkout master
Go on the branch you want to delete
Get all new changes from svn
Update this branch to the last version
git rebase origin
Switch back to the master branch and rebase.
git checkout master
Finally, delete the branch
git branch -d mywork
NOTE: If you haven't waited long enough after your commit, it is possible that 'git fetch' did not get your svn commit and git will continue to believe that you have local changes, which will prevent "git branch -d" from succeeding. It's best to redo the steps later, (The repo is updated every 3 minutes) but you can also instruct git to force-delete your branch.
Note that when you delete your branch, it will give you the SHA-1 hash for its tip:
Deleted branch mywork (was 123abc0).
You can then recover the branch via:
git checkout -b mywork 123abc0
If you forget the hash, you can find it via git reflog. (Reference: Can I recover branch after the deletion in git?)
If you commit to master, updating will be messy.
You can prevent this by adding a pre-commit hook that checks if you're in master and stops you from doing this. Create a file named chromium/src/.git/hooks/pre-commit and add the below to it, then mark executable. (Blink developers: add in blink directory as well.)
If you've accidentally uploaded a change list from master, you can clear the association of an issue number with master via:
git cl issue 0
If you've accidentally committed to master, then, after copying your work to a new branch (e.g., make patch and then apply to new branch), you can clean up master by deleting your accidental commit as per this answer to How to undo the last Git commit? -- see more details there.
git reset --hard HEAD~1
Sometimes you'll get the message "You have unstaged changes." when you personally don't, often due to a directory that has been moved or delete. You can fix this by moving the directory outside of the repo directory (or deleting it), and then trying gclient sync again.
It is also possible that you're getting this due to local changes (or other problems) in the depot_tools directory. You can fix these by going to depot_tools and resetting:
git reset --hard HEAD
Your source tree includes many other repositories in subdirectories - mainly in third_party, but also elsewhere. See src/DEPS for the full list.
Each subdirectory is its own git tree, so you should start a branch inside a subdirectory if you want to work there. Be sure to commit and checkout master again when you want to sync your tree again later!
If you wish to commit to one of these repositories, you will need to configure git svn like you did for the main Chromium repository.
However, in order to ensure that git cl dcommit will do the right thing, some additional configuration is needed in order to match the svn repository the git mirror is mirroring from.
To do so, run:
And look for the line beginning with git-svn-id: . For example, if you wanted to commit to ffmpeg (src/third_party/ffmpeg), running git log would show something like git-svn-id: http://src.chromium.org/svn/trunk/deps/third_party/ffmpeg@12345 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
If the URL starts with svn://svn.chromium.org/svn, the steps are very similar to SVN setup for committers, replacing every occurrence of trunk/src with whatever the path was in the git log command was (eg:trunk/deps/third_party/ffmpeg).
If the URL starts with http://src.chromium.org/svn or https://src.chromium.org/svn, you will need to configure git svn to fetch from that URL, but when committing, to use svn://svn.chromium.org/svn. If the URL was https://, use https://' instead of http://` below:
The key is setting svn-remote.svn.pushurl to the read-write URL of the project, even though the URL passed to git svn init may be the read-only URL.
For projects hosted on code.google.com (for example, gyp) there's slightly different incantations required. For example with gyp:
git svn init https://gyp.googlecode.com/svn -Ttrunk --rewrite-root=http://gyp.googlecode.com/svn
git svn info
From a branch, find the Git Commit ID (SHA1) of the revision you want to revert
Revert the change and commit it locally
git revert <sha1>
Upload for review
git cl upload
git cl dcommit --tbr
Never commit changes to .DEPS.git. This file is maintained by an automated system based on what's in DEPS and your changes will be overwritten.
While Chromium's main source server remains in Subversion, rolling DEPS using the Git workflow requires a couple of extra steps:
1. Start out with a SVN revision you want to roll a given dependency in DEPS to.
2. Find the corresponding Git SHA1 commit ID to the SVN revision you are rolling to. You can usehttps://chromium.googlesource.com/chromium/src to find the SHA1 commit ID for a given project + SVN revision.
3. Update your .DEPS.git to that project's SHA1 commit ID, testing this change in your Git working copy. When you're through testing, remove this change so you don't accidentally modify .DEPS.git.
4. Modify DEPS to use the desired SVN revision. (Once change on DEPS is committed by you, the automated system commits update on .DEPS.git soon)
If you want to locally test changes to .DEPS.git. You can manually generate .DEPS.git by running (from the src) directory:
python tools/deps2git/deps2git.py -o .DEPS.git
Just remember not to check it in!
If you are developing using a SVN dependency that's not in any of the mirrored Git repos (eg. a development branch), follow these instructions:
1. Make sure your checkout is up-to-date by running 'gclient sync'.
2. Edit src/.DEPS.git to point your dependency at the SVN equivalent for your change. (eg. change 'src/third_party/v8-i18n' to point to http://v8-i18n.googlecode.com/svn/branches/globalization@45)
3. Move or remove that dependency's directory in your checkout (eg. rm -rf src/third_party/v8-i18n)
4. Re-run 'gclient sync' to pull that SVN checkout locally.
5. Verify your change. You're free to test that dependency now. If you used a SVN URL that allows you to commit back to that repo, you can also use it to develop against that repo.
6. Revert your change to src/.DEPS.git. Never commit changes to .DEPS.git.
If you are adding a new repository to pull from, make sure that repository's svn URL can be parsed by the tools by running:
python tools/deps2git/deps2git.py -o .DEPS.git
Don't manually check in changes to .DEPS.git (see "Rolling Deps" above).
Make sure that the repository in question is mirrored at chromium.googlesource.com. To mirror a repository or add a custom URL mapping to deps2git.py, please file an infrastructure ticket.
If the Git command line doesn't work for you, please ensure that your environment variables like EDITOR, HOME, and GIT_SSH are all set to strings not enclosed in double quotes. We have fixed at least one error caused by this previously. It's possible that overusing quotes in your variables will cause other errors, as well.
Check out these links:
After you read those and understand the git-svn commands and workflow, then you'll realize that all git-svn does is set up and manage a new git remote. If you don't know about git remotes, you'll want to learn more about those, too.
Using the Cocoa version of Emacs as the EDITOR environment variable on Mac OS will cause "git commit" to open the message in a window underneath all the others. To fix this, create a shell script somewhere (call it $HOME/bin/EmacsEditor? in this example) containing the following:
and in your .bashrc or similar,
git-cl defaults to using 50% similarity as a threshold for detecting renames. This is sometimes inappropriate, e.g., if splitting off a small file from a large file (in which case you want a smaller threshold, to avoid false negatives), or when adding a small file (in which case you want a larger threshold, to avoid false positives from common boilerplate). This is controlled by the add_git_similarity function in git_cl.py, and you can set threshold to a given value for a branch (saved in config for that branch), or not look for copies on a specific upload (but not saved in config for the branch):
git cl upload --similarity=80 # set threshold to 80% for this branch
Managed mode is a deprecated feature of gclient. It was conceived to give an easier workflow for newcomers to git, but turned out to be full of surprising behaviors. It has thus been deprecated, unmanaged mode is the default, and existing users of managed mode are encouraged to change to unmanaged mode.
To check which mode you are using, check .gclient (the gclient config file) and see the value of the "managed" flag. To switch to unmanaged mode from managed mode:
To make the Blink repo also unmanaged, first fetch blink and then:
The main difference between managed mode and unmanaged mode is that in managed mode, local branches track local master branch instead of origin/master, and gclient “manages” the branches so that they stay in sync. However in practice this leads to two master branches (local master and origin/master) that go out of sync and prevent further uploads/commits. With unmanaged mode you always have only one master: origin/master. The local master still exists but is not treated in any special way by the tools.
If you find yourself needing help with the new workflow, please file a bug with the infrastructure team athttps://code.google.com/p/chromium/issues/entry?template=Build%20Infrastructure