Difference between revisions of "Development:Using Git for Camino development"

From Camino Wiki
Jump to navigation Jump to search
(Murph's aliases are confusing to even a regular git user.)
Line 29: Line 29:
  
 
''(The last line installs the documentation.  Building it directly requires a mess of dependencies ;)).''
 
''(The last line installs the documentation.  Building it directly requires a mess of dependencies ;)).''
 +
 +
===Binary Installer===
 +
Git can also be installed with a binary installer hosted at [http://code.google.com/p/git-osx-installer/downloads/list?can=3 Google Code]
  
 
==Initial Git configuration==
 
==Initial Git configuration==
Line 140: Line 143:
 
This creates an empty Git repository.  At this point, issuing a status command shows which files Git sees but is not yet tracking:
 
This creates an empty Git repository.  At this point, issuing a status command shows which files Git sees but is not yet tracking:
  
$ <code>git st</code><br/>
+
$ <code>git status</code><br/>
 
<pre>
 
<pre>
 
# On branch master
 
# On branch master
Line 161: Line 164:
 
Now, showing status lists all of the files that Git has staged to commit:
 
Now, showing status lists all of the files that Git has staged to commit:
  
$ <code>git st</code><br/>
+
$ <code>git status</code><br/>
 
<pre>
 
<pre>
 
# On branch master
 
# On branch master
Line 188: Line 191:
 
Finally, create a new, initial commit
 
Finally, create a new, initial commit
  
$ <code>git ci -m "Initial import"</code><br/>
+
$ <code>git commit -m "Initial import"</code><br/>
  
 
=Day to day Camino development with Git=
 
=Day to day Camino development with Git=
Line 200: Line 203:
 
When I want to begin work on a certain bug, I will create a new branch.  The following command is a shortcut to create a new branch and also check it out:
 
When I want to begin work on a certain bug, I will create a new branch.  The following command is a shortcut to create a new branch and also check it out:
  
$ <code>git co -b NameOfCurrentBug</code><br/>
+
$ <code>git checkout -b NameOfCurrentBug</code><br/>
 
 
 
Now, you can edit away.  Anytime you need to switch contexts, maybe to work on a different bug that suddenly came up or to step aside and review a patch, you can just keep creating branches to do this:
 
Now, you can edit away.  Anytime you need to switch contexts, maybe to work on a different bug that suddenly came up or to step aside and review a patch, you can just keep creating branches to do this:
  
$ <code>git co -b NameOfCurrentBugToReview master</code><br/>
+
$ <code>git checkout -b NameOfCurrentBugToReview master</code><br/>
  
 
''You can list the branch you want to stem from as the last argument.  In this case, we weren't on the master branch, so we explicitly told Git to branch from there rather than defaulting to the current one.''
 
''You can list the branch you want to stem from as the last argument.  In this case, we weren't on the master branch, so we explicitly told Git to branch from there rather than defaulting to the current one.''
Line 212: Line 215:
 
Your Git repo's master branch is our mirror to the pristine CVS source.  Whenever you want to sync with the official Camino repository, just checkout your master branch, perform an update through CVS, and commit the changes:
 
Your Git repo's master branch is our mirror to the pristine CVS source.  Whenever you want to sync with the official Camino repository, just checkout your master branch, perform an update through CVS, and commit the changes:
  
$ <code>git co master</code><br/>
+
$ <code>git checkout master</code><br/>
 
$ <code>cd /PathToCaminoRepository/mozilla</code><br/>
 
$ <code>cd /PathToCaminoRepository/mozilla</code><br/>
 
$ <code>cvs update -dP client.mk</code><br/>
 
$ <code>cvs update -dP client.mk</code><br/>
Line 222: Line 225:
  
 
Optionally, you can easily see what was changed upstream:<br/>
 
Optionally, you can easily see what was changed upstream:<br/>
$ <code>git st</code><br/>
+
$ <code>git status</code><br/>
  
 
Finally, add/commit the updates into Git:<br/>
 
Finally, add/commit the updates into Git:<br/>
 
$ <code>git add .</code><br/>
 
$ <code>git add .</code><br/>
$ <code>git ci -m "Sync with CVS"</code><br/>
+
$ <code>git commit -m "Sync with CVS"</code><br/>
  
 
===Incorporating the latest CVS changes into your working branches===
 
===Incorporating the latest CVS changes into your working branches===
Line 232: Line 235:
 
We now have pulled the latest CVS updates into Git, but the branches that we're working on need to be merged with the latest updates as well, which are kept on the master branch.  For this, we can use the ''git rebase'' command.
 
We now have pulled the latest CVS updates into Git, but the branches that we're working on need to be merged with the latest updates as well, which are kept on the master branch.  For this, we can use the ''git rebase'' command.
  
$ <code>git co NameOfBugBranch</code><br/>
+
$ <code>git checkout NameOfBugBranch</code><br/>
 
$ <code>git rebase master</code><br/>
 
$ <code>git rebase master</code><br/>
  
Line 249: Line 252:
 
To check out branches that you had on the other machine:
 
To check out branches that you had on the other machine:
  
(SecondMac)$ <code>git co -b BranchName origin/BranchName</code><br/>
+
(SecondMac)$ <code>git checkout -b BranchName origin/BranchName</code><br/>
 
<pre>
 
<pre>
 
Branch BranchName set up to track remote branch refs/remotes/origin/BranchName.
 
Branch BranchName set up to track remote branch refs/remotes/origin/BranchName.
Line 258: Line 261:
 
Edit files, then commit the changes locally:
 
Edit files, then commit the changes locally:
  
$ <code>git ci -am "Changed a few files"</code><br/>
+
$ <code>git commit -am "Changed a few files"</code><br/>
  
 
Push my updates back onto the other machine where we cloned from:
 
Push my updates back onto the other machine where we cloned from:

Revision as of 10:31, 31 May 2009

How to use Git locally to supercharge your Camino development workflow.
by Sean Murphy
on 2009-03-23

Even though the Camino source is managed in CVS, you can use Git locally to track the official repository. Doing so offers many advantages to the development process. You can easily work on multiple bugs at once, you can stash your code or make a new branch to perform a review on the side, and you can easily keep your work synchronized on multiple computers.

Prerequisites

This article assumes you have already checked out a fresh copy of the Camino source. Follow our build instructions to do this. Note: you don't need to build yet, so after setting things up you can issue the following command to checkout the source only:

$ make -f client.mk checkout MOZ_CO_PROJECT=macbrowser

Note: Throughout the article /PathToCaminoSource/ is the directory that contains a mozilla/ subfolder with the source tree, and a CaminoObj/ folder for all the build objects.

Installing Git on Mac OS X

The short and sweet steps to install Git on the Mac:

Note: Replace the "1.6.2.1" Git version below with the most current release. Check http://git-scm.com/ to find out what the current revision is.

$ curl http://kernel.org/pub/software/scm/git/git-1.6.2.1.tar.bz2 | tar xj
$ cd git-1.6.2.1
$ ./configure
$ make prefix=/usr/local
$ sudo make prefix=/usr/local install
$ curl http://www.kernel.org/pub/software/scm/git/git-manpages-1.6.2.1.tar.bz2 | sudo tar xj -C /usr/local/share/man

(The last line installs the documentation. Building it directly requires a mess of dependencies ;)).

Binary Installer

Git can also be installed with a binary installer hosted at Google Code

Initial Git configuration

At minimum, you'll need to tell Git about yourself:

$ git config --global user.name "Your Name"
$ git config --global user.email "name@email.com"

Additionally, some other settings can make interacting with Git more pleasant.

Display Git output with color:

$ git config --global color.ui auto
$ git config --global color.status auto
$ git config --global color.diff auto
$ git config --global color.branch auto
$ git config --global color.interactive auto

Make some shortcuts for common commands, and support your svn habits:

$ git config --global alias.st status
$ git config --global alias.ci commit
$ git config --global alias.co checkout

e.g. git checkout can be shortened to git co

Excluding certain files from being tracked by Git

Just like .cvsignore and Mozilla's .hgignore, we'll create an ignore file for Git to exclude certain files we do not want it to manage.

Exclude files for all repositories

You can create a global ignore file to always exclude files from any Git repository on your machine. In here we'll list certain Mac development related files we'll never want Git to see and ask us if we want to track it.

Save this file as ~/.gitignore

	.DS_Store
	*.orig
	*.rej
	*~
	
	# The following ignores all files in the .xcodeproj bundle,
	# And then adds back in only the project (skipping the user files)
	*.xcodeproj/
	!*.xcodeproj/project.pbxproj
	
	*~.nib
	*.swp
	
	*.o
	.#*
	a.out

Then, we have to configure Git to use our global excludes file:

$ git config --global core.excludesfile ~/.gitignore

Exclude Mozilla specific files

Git will also look for a .gitignore file in the root directory of each repository. In here we can exclude additional files that are specific to Camino development, ones that we would not want to ignore across the entire system.

Save this file as /PathToCaminoSource/.gitignore

	# Exclude certain Mozilla files (user specific / auto generated)
	.mozconfig.mk
	.mozconfig.out
	configure$
	config.cache
	config.log
	ID
	Makefile
	config.status
	.client-defs.mk
	config-defs.h
	unallmakefiles
	nss
	mozilla-config.h
	mozconfig
	.mozconfig

	# Empty marker file that's generated when we check out NSS
	security/manager/.nss.checkout

	# We ignored Xcode's build/ directory globally in Git
	# But the mozilla source has */build/ directories we'll need.
	# Cancel the ignore, then exclude only the camino Xcode build directory.
	!build
	*camino/build

	# Ignore CVS metadata
	CVS
	.cvsignore
	cvsco.log

	# Build objects
	dist
	*.pyc
	CaminoObj

Initializing your Git repository

We're now ready to create a new Git repository. I use the mozilla/ directory inside of my Camino source tree as the root of my repository

$ cd /PathToCaminoSource/

$ git init

This creates an empty Git repository. At this point, issuing a status command shows which files Git sees but is not yet tracking:

$ git status

	# On branch master
	#
	# Initial commit
	#
	# Untracked files:
	#   (use "git add <file>..." to include in what will be committed)
	#
	#	.gitignore
	#	mozilla/

Note: We do want to manage the .gitignore file, as otherwise we'd need to hand create it and keep it in sync on each clone of the repository.

Now we're ready to add all of the files into the Git repository.

$ git add .

Now, showing status lists all of the files that Git has staged to commit:

$ git status

	# On branch master
	#
	# Initial commit
	#
	# Changes to be committed:
	#   (use "git rm --cached <file>..." to unstage)
	#
	#	new file:   mozilla/browser/config/version.txt
	#	new file:   mozilla/docshell/Makefile.in
	#	new file:   mozilla/docshell/base/Makefile.in
	#	new file:   mozilla/docshell/base/crashtests/369126-1.html
	#	new file:   mozilla/docshell/base/crashtests/403574-1.xhtml
	#	new file:   mozilla/docshell/base/crashtests/crashtests.list
	#	new file:   mozilla/docshell/base/nsAboutRedirector.cpp
	#	new file:   mozilla/docshell/base/nsAboutRedirector.h
	#	new file:   mozilla/docshell/base/nsCDefaultURIFixup.idl
	#	new file:   mozilla/docshell/base/nsCDocShell.idl
	#	new file:   mozilla/docshell/base/nsDSURIContentListener.cpp
	#	new file:   mozilla/docshell/base/nsDSURIContentListener.h
	#	new file:   mozilla/docshell/base/nsDefaultURIFixup.cpp
	...

Finally, create a new, initial commit

$ git commit -m "Initial import"

Day to day Camino development with Git

Now, this is where the real fun begins, and when you notice that all the above setup was extremely worth the effort!

Creating a branch to work on a bug

Git, by default, will create a master branch. This is where I keep the official, untouched source from Camino's CVS repository.

When I want to begin work on a certain bug, I will create a new branch. The following command is a shortcut to create a new branch and also check it out:

$ git checkout -b NameOfCurrentBug

Now, you can edit away. Anytime you need to switch contexts, maybe to work on a different bug that suddenly came up or to step aside and review a patch, you can just keep creating branches to do this:

$ git checkout -b NameOfCurrentBugToReview master

You can list the branch you want to stem from as the last argument. In this case, we weren't on the master branch, so we explicitly told Git to branch from there rather than defaulting to the current one.

Staying in sync with the Camino CVS repository

Your Git repo's master branch is our mirror to the pristine CVS source. Whenever you want to sync with the official Camino repository, just checkout your master branch, perform an update through CVS, and commit the changes:

$ git checkout master
$ cd /PathToCaminoRepository/mozilla
$ cvs update -dP client.mk
$ make -f client.mk checkout

Many times though, you only need/want to update the mozilla/camino/ tree:
$ cd /PathToCaminoRepository/mozilla/camino
$ cvs update -dP

Optionally, you can easily see what was changed upstream:
$ git status

Finally, add/commit the updates into Git:
$ git add .
$ git commit -m "Sync with CVS"

Incorporating the latest CVS changes into your working branches

We now have pulled the latest CVS updates into Git, but the branches that we're working on need to be merged with the latest updates as well, which are kept on the master branch. For this, we can use the git rebase command.

$ git checkout NameOfBugBranch
$ git rebase master

You can read more about git rebase, and how it differs from git merge.

Working on multiple Macs

One of the other huge advantages of using Git locally is that it easily makes it possible to develop the same feature across multiple machines, keeping all of your work in sync.

On your other Mac, we'll clone the original repository:

(SecondMac)$ git clone ssh://FirstMac/~/PathToCaminoRepository PathToLocalCaminoRepository

When you clone, Git sets up a remote corresponding to the original machine, called origin. You can use this remote identifier to push and pull updates to and from your other Mac.

To check out branches that you had on the other machine:

(SecondMac)$ git checkout -b BranchName origin/BranchName

	Branch BranchName set up to track remote branch refs/remotes/origin/BranchName.

This output means that Git automatically configured this new branch as a "tracking" branch, and any remote operations will know to work against the branch on the original machine. Learn more about what that means here.

Edit files, then commit the changes locally:

$ git commit -am "Changed a few files"

Push my updates back onto the other machine where we cloned from:

$ git push

Or, on the other end, use git pull and git fetch on the original machine. See the community Git book for more information about the distributed workflow in Git.

The Gotcha: Communicating with CVS on your other Mac

Our Git repository does not track or keep a copy of the CVS metadata. This means that when we clone the repository onto another machine, we are unable to actually sync or otherwise communicate with Camino's CVS repo on any secondary machine. Tracking the CVS/ information creates too much noise in the Git repository and I haven't found any sane way to keep this data in Git.

Therefore, anytime you need to interact with the official CVS repository, it has to be done on the original machine. To sync with upstream changes on the Camino trunk, you first need to cvs update on the original Mac commit the changes into the master branch like always (this can be done over SSH since you're remote). Then, you can then git fetch/pull the updates through origin/master branch on your remote repository.

Performing cvs diff and creating patches must also be done on the original machine, unfortunately. To do this, just push or pull your changes onto the machine with the original repository (and CVS information), and then perform a cvs diff from the Git branch your changes are on. (It is possible to perform a diff with Git, from your working branch to a freshly synced master, but the patch will appear like it's from Git and I'm not sure if this is acceptable or not, so I usually just do the regular CVS routine).

Appendix: Misc Git tips

Bash enhancements for use with Git

Tab completion

Git includes a bash script that offers tab-competion of commands, branch names, etc. It's easy to install and a joy to have.

  1. Look for the "git-completion.sh" file. It is usually found in git-x.x.x.x/contrib/completion/, but I think recently a Git patch has it moving to /usr/local/share/git-completion/ during installation.
  2. Copy this file to somewhere (e.g. ~/.git-completion.sh).
  3. Added the following line to your .bashrc:

source ~/.git-completion.sh

Branch name in prompt

Additionally, it is extremely helpful to also have your bash prompt list the current branch you are on. Enable this by doing the following:

  1. In your bash profile, add the following to your PS1:

$(__git_ps1 " (%s)")
(If you aren't in a Git repo, it won't display anything).