Git Branching Illustrated

The excellent Git - SVN Crash Course is somewhat too succint on remote shared repositories and branching. Here I try to provide some of the missing necessary bits.

If you prefer to see it as a shell animation, download and run this script. You just need to keep closing the gitk window to see it animated.

setup a blank bare repo

mkdir bare-repo
cd bare-repo
git init --bare
cd ..

annie starts the development

git clone bare-repo annie
cd annie
gitk --all
echo 'hello' > README
git add README
git commit -m 'annie commits hello'
  # the commit is local only! it's not published yet!
gitk --all
git push origin master:master
  # send our commits to the upstream repo (called 'origin')
  # we're specifically sending our master (the first one) to their master
  # shorter version: git push origin master
cd ..

bob joins and adds his word

git clone bare-repo bob
cd bob
echo 'bob adds hello' >> README
git commit README -m 'bob adds his hello'
  # note the fine-grained committing, specifying only the files we commit
  # you may also use 'git commit -a' to commit all modified files
git push origin master
cd ..

annie starts a local branch

cd annie
git pull # get changes from upstream
git branch annies-experiment
  # note that we are *not* on the branch yet
git checkout annies-experiment
  # going to the new branch
cat README | sed 1iannie-adds-prefix > README.new
mv README.new README
git commit -a -m "annie's experiment"
cd ..

in the meantime, bob develops master further

cd bob
git pull
  # note that bob does not see annie's local branch at all
echo 'bob develops further' >> README
git commit -a -m 'bob develops further'
git push origin master
cd ..

annie joins bob's development on the master branch

cd annie
git fetch
git checkout master
git merge origin/master
  # make our local master branch up-to-date
echo 'annie develops master further' >> README
git commit -a -m 'annie develops further'
  # this commit was still only local
git push origin master
  # let's push our development upstream
cd ..

annie wants to publish her branch for bob to join

cd annie
git push origin annies-experiment:annies-experiment
  # publish our branch in the shared repo
  # origin ... is the shared repo
  # annies-experiment (the former) ... is the local name of the branch
  # annies-experiment (the latter) ... is the remote name of the branch
cd ..

bob joins development on annie's branch

cd bob
git fetch
  # bob came back from holiday and notices the master has evolved
  # and annie has published her branch
git checkout --track -b annies-experiment origin/annies-experiment
  # bob creates a local branch to track annie's branch in origin
cat README | sed 1ibob-adds-one-more-prefix > README.new
mv README.new README
git commit -a -m "bob joins annie's experiment"
  # this commit was still only local!
git push
  # try pushing all branches:
  #   annies-experiment will succeed
  #   master will be rejected because bob's master is out of date
cd ..

annie develops independently her branch

cd annie
git checkout annies-experiment
cat README | sed 1iannie-adds-one-more-prefix > README.new
mv README.new README
git commit -a -m "annies adds one more prefix"
  # this commit was only local
cd ..

later, annie gets bob's updates

cd annie
git fetch
  # annie gets bob's updates and sees that bob has further developed her branch
git merge origin/annies-experiment
  # annies plans to merge bob's work and her work
  # but a conflict occurs
cat README | sed '1,5d;6iannie-and-bob-added-one-more-prefix' > README.new
mv README.new README
git commit -a -m "annies merges her and bob's work"
git push
  # annie pushes the merge upstream
cd ..

bob wants to merge annie's experiment into the master branch

cd bob
# first, bob makes all his local branches up to date
git pull
  # only the current branch (annies-experiment) gets up to date
git checkout master
git pull
  # now also the master is up to date
git merge annies-experiment
  # we are on (local) master, modifying it to include (local) annies-experiment
  # the merge had no conflicts! awesome!
  # ...so a local commit happened right away, unlike above
git push
  # push the merge upstream
cd ..

annie get's her repo updated

cd annie
git fetch
  # annie sees her branch was merged to the master => no need to stay alone
git checkout master
  # annie will work on the master now
git pull
  # and makes the master up-to-date





Ondřej Bojar, $Date: 2011-08-16 13:10:12 $