[[PageOutline]] = Tips and Tricks for using Git with WebKit = * [wiki:"Moving to Git" Proposal for moving WebKit development to Git] == Install == Mac users: * Update your Git install: http://code.google.com/p/git-osx-installer/ * Update your SVN install (for `git-svn` bindings): http://www.open.collab.net/downloads/community/ [http://www.debian.org Debian] users: {{{ sudo apt-get install git-core }}} Windows users: http://code.google.com/p/msysgit/ You can also download Git binaries directly from the [http://git-scm.com/download official site!] == Checkout == To checkout WebKit using git: {{{ git clone git://git.webkit.org/WebKit.git WebKit }}} If you are a WebKit committer and want to be able to commit changes to the Subversion repository, or just want to check out branches that aren't contained in WebKit.git, you will need track the Subversion repository. To do that, inform `git-svn` of the location of the WebKit SVN repository, and update the branch that `git-svn` uses to track the Subversion repository so that it will re-use the history that we've already cloned from `git.webkit.org` rather than trying to fetch it all from Subversion: {{{ cd WebKit git svn init -T trunk http://svn.webkit.org/repository/webkit git update-ref refs/remotes/trunk origin/master }}} This will add the following section to your `.git/config`: {{{ [svn-remote "svn"] url = http://svn.webkit.org/repository/webkit fetch = trunk:refs/remotes/trunk }}} You can then run the following command to have `git-svn` rebuild its metadata from your local repository, and to pull any recent commits from the WebKit SVN repository. {{{ git svn fetch }}} == Updating == If you're not tracking the Subversion repository the following command will fetch new commits from `git.webkit.org`: {{{ git fetch }}} You can then merge or rebase your local branches with `origin/master` to pick up the new commits. If you are tracking the Subversion repository, this command will fetch information about new commits from Subversion, reset your local branch to match Subversion exactly, and then apply your local commits on top: {{{ git svn rebase }}} If you'd like to fetch new commits from the Subversion repository without moving your local branch, you can use the following command: {{{ git svn fetch }}} == webkit-patch, check-webkit-style and git == webkit-patch commands all work with git. There's a couple extra flags that help dealing with git branches and local commits, namely --squash, --no-squash and --git-commit. There are two camps on using git with webkit-patch. branch-per-bug and commit-per-bug. In the former, there is one patch per bug and all local commits are essentially one patch. In the latter, there's 1+ local commits per bug and possibly multiple bugs addressed on a single branch. The branch-per-bug use case is met entirely by always using --squash. The commit-per-bug use case is met by a combination of --git-commit and --no-squash, both of which have non-trivial and overlapping FIXMEs. If you get sick of typing --squash or --no-squash, you can set the webkit-patch.squash git config parameter to true/false. --squash: Treat all changes in the local branch as a single patch (local commits + working copy changes). Doesn't actually modify your tree until you land, at which point it squashes all local changes into a single local commit and then lands that. * FIXME: --squash commits too much if you branch is not fully merged/rebased to trunk https://bugs.webkit.org/show_bug.cgi?id=38852. --git-commit: operate on the given git commit(s). Commits can be specified as single commits (e.g. HEAD^) or multiple (e.g. HEAD~2..HEAD). * FIXME: landing doesn't work if it needs to modify the ChangeLog https://bugs.webkit.org/show_bug.cgi?id=39073. * FIXME: When passing a commit range, all the commits get squashed into one. --git-commit should respect --squash and --no-squash instead. * FIXME: Until the above is fixed, specifying both should throw an error https://bugs.webkit.org/show_bug.cgi?id=38393. --no-squash: Operate only on working-copy changes, with the exception of webkit-patch land. land: If there are *only* working copy changes, commit them locally and then git svn dcommit. Otherwise, if there are local commits, then just git svn dcommit. * FIXME: --no-squash is unfinished. It needs a lot of work. It's not 100% clear what the right behavior is. Ideally someone from the commit-per-bug camp could iterate on this and make it work for that use-case. One world that would make things consistent and reliable: a) Always operate on both working copy changes and local commits. b) Always treat each local commit separately, not just for land, e.g., webkit-patch upload will upload each local commit and working-copy changes separately. FWIW, fixing --no-squash to operate on local commits is 99% of the work to making --git-commit ranges respect --no-squash. * FIXME: This also suffers from https://bugs.webkit.org/show_bug.cgi?id=39073 in the same way --git-commit does. If you leave out --squash and --no-squash and there's only a single local commit or only working copy changes in a branch, then the commands will work on that single patch. Otherwise they raise an error saying to use --squash or --no-squash. * FIXME: Make one of --squash or --no-squash the default. The current default is inconsistent and confusing. == Commit manually through git-svn directly == If you have been granted commit access to WebKit's SVN repository it is possible to work entirely with git and to commit through `git-svn`, however using webkit-patch land is encouraged since it deals with changelogs, commit logs and bugzilla for you. After you have configured your working copy to track the Subversion repository you can: 1. Create a `tot_staging` branch or whatever name you choose 2. Apply a patch, cherry-pick a commit, or even merge a branch if it has been reviewed 3. Run `git svn rebase` and fix any ChangeLog conflicts that might result 4. Ensure the git log entry for your local commit contains an accurate copy of all the Changelog entries for your commit. 5. And then when everything is ready-- {{{ git svn dcommit }}} Since "git svn dcommit" creates a revision in the subversion repository for each local commit, you may need to squash (i.e. combine) commits to ensure that your commit to the WebKit repository will create just one revision. You can do this, for example, by using-- {{{ git rebase -i HEAD~n }}} where n is the number of commits you want to see in the interactive editor. You can use `git commit -a --amend` for example to amend an existing local commit and avoid creating additional commits that you may need to squash later on. As you may have guessed from step 4 above, "git svn dcommit" does not use the "commit-log-editor" setting to create a commit message to store in the remote Subversion repository. Instead it simply uses the commit message already associated to the local commit, so you need to ensure that it is an accurate copy of all your commit's Changelog entries. This is somewhat different from committing with Subversion, where "svn commit" does intervene with "commit-log-editor" to create a commit message for the remote repository. == WebKit Script support for Git == The various scripts in `WebKitTools/Scripts` have been made to work pretty well with Git. Here are some of the specific things you can do with them: * Telling the various scripts to '''append the git branch name to every build'''. This is especially useful so you don't clobber your previous branch's build when you switch branches {{{ git config core.webKitBranchBuild (true|false) //the default is off }}} * Overriding the core.webKitBranchBuild setting for a specific branch {{{ git config branch.$branchName.webKitBranchBuild (true|false) }}} * Using '''prepare-Changelog''' with git {{{ WebKitTools/Scripts/prepare-ChangeLog --git-commit=$committish --git-reviewer="Foo Reviewer" }}} * Using '''resolve-ChangeLog''' with git. Assuming you got a conflict merging a ChangeLog file, this tool will reapply the patch using {{{patch --fuzz=3}}} so that your change lands at the top of the ChangeLog file. If the patch was successfully applied, {{{git-add}}} is run on the ChangeLog file. Note that this tool does not change the date of the ChangeLog entry (unlike {{{svn-apply}}}). {{{ WebKitTools/Scripts/resolve-ChangeLogs path/to/ChangeLog [path/to/ChangeLog ...] }}} * Telling Git to use '''resolve-ChangeLogs''' automatically as a merge-driver for ChangeLogs (assumes resolve-ChangeLogs is in your path) {{{ git config merge.changelog.driver "resolve-ChangeLogs --merge-driver %O %A %B" }}} * Using '''commit-log-editor''' with git will automatically insert the ChangeLog entry as your commit message (assuming {{{WebKitTools/Scripts}}} is in your path) {{{ git config core.editor commit-log-editor }}} If you want to make sure log gets regenerated from ChangeLog entry each time you modify an already existing commit, use --regenerate-log: {{{ git config core.editor "commit-log-editor --regenerate-log" }}} * If you do not manually generate a ChangeLog entry and you have staged changes in your working tree, '''commit-log-editor''' will automatically generate a commit message in the WebKit ChangeLog entry format when you do 'git commit'. You can control this behaviour with the git configuration option '''webkitGenerateCommitMessage''' on a global or per-branch basis. {{{ git config core.webkitGenerateCommitMessage (true|false) //the default is true git config branch.$branchName.webkitGenerateCommitMessage (true|false) }}} == Misc. Tips and Tricks == * You can setup '''Git shell completion and branch name in your bash prompt.''' In your /contrib/completion directory you will find a 'git-completion.bash' file. The command "git --exec-path" may help you determine your path to git. Follow the instructions in that file to enable shell completion. Here is a nice bash prompt for instance {{{ PS1='\[\033[41;1;37m\]\u@\h:\[\033[40;1;33m\]\W$(__git_ps1 " (%s)")>\[\033[0m\] ' }}} * You can set up '''multiple working directories to work on more than one branch at a time.''' In your /path/to/git/source/contrib/workdir directory you will find a 'git-new-workdir' script that can create new working directories. The usage is {{{ ./git-new-workdir [] }}} * Colorize various git commands {{{ git config --global color.status auto git config --global color.diff auto git config --global color.branch auto }}} * Important git config settings {{{ git config --global user.name "Foo Bar" git config --global user.email "foo@webkit.org" }}} * If you're using `git-send-bugzilla` or `webkit-patch` you may also want git to remember your bugzilla credentials: {{{ git config --global bugzilla.username "name@example.com" git config --global bugzilla.password "yourpassword" }}} == Ignores == * You can setup your git repository to ignore the same files that are ignored in the tracked Subversion repository with: (this will take some time) {{{ git svn show-ignore >> .git/info/exclude }}}