A Git Primer cja@umich.edu 22 Jun 11 Verson 1.0 0 The Git Primer This is a short introduction to the use of Git to manage your development projects. It is meant to get you up and running using Git in a minimum of time. It is not a comprehensive guide to all of Git's features; for example, it does not discuss the index at all. For more extensive documentation, please see Section 1.3. 1 Installing Git Currently, the multi-platform client software of choice is called msysGit. An excellent alternative for Windows users only (at time of writing) is TortoiseGit. 1.1 Installing msysGit on Windows Visit http://git-scm.com/download and select Windows inside the red box. On the "msysgit Git for Windows" download page that appears, select the filename on the "full installer for official Git" line (currently version 1.7.3.1). On the next page, click on the filename again to download it, then run the installer. If you get a popup warning about an unknown publisher, you can click "Run". If you get a User Account Control warning about an unidentified program that wants access to your computer, you can click "Allow". Then follow the Git Setup Wizard, accepting all defaults, except on the "Select Components" pane, check the "Git Bash Here" and "Git GUI Here" components. You can use either the Git command line interface or the fancy new GUI. For the former, go to All Programs, find the Git entry, and click it; you'll see "Git Bash" and "Git GUI" underneath. Clicking "Git Bash" will start a BASH shell, mostly identical in behavior to the BASH shell on UNIX and Linux. "Git GUI" will start the Git GUI. The GUI invokes the Git command-line commands under the covers while showing you graphically the state of your repository. This primer genereally assumes you are using the Git comamnd line interface. When visualizing complex sequences of commits and merges, however, the gitk GUI tool is very useful; please see Section 4.5. 1.2 Other operating systems Visit http://git-scm.com/download and select your operating system in the red box, and proceed as above. For Linux (and other operating systems that are not listed) you will be offered the msysGit source code, which you can download and compile; see the instructions in the INSTALL file in the top-level downloaded directory. 1.3 Installing TortoiseGit on Windows Visit http://code.google.com/p/tortoisegit/ and select the Download tab, then download the appropriate (32- or 64-bit) client. TortoiseGit requires msysGit, so you should download and install that product first, as described in earlier. 1.4 Documentation Documentation is installed in the form of Linux manual pages for all Git commands when you install msysGit. If you want information about git, type: $ man git If you want information about a git command, say "commit," type: $ man git-commit This documentation is quite complete, but does assume you understand the Git framework. You can also navigate to online help documentation using the Git GUI by navigating to Help | Online Docoumentation. There is also considerable information on the web, for example: A good online tutorial: http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html Another tutorial, which I have not used: http://gitref.org/ For folks used to SVN, a "crash course" in converting to Git: http://git-scm.com/course/svn.html A "crib sheet" of common Git commands, grouped by role (developer, integrator, etc.), including per-user shared repository authorization: http://www.kernel.org/pub/software/scm/git/docs/everyday.html Finally, the O'Reilly book by John Loeliger, "Version Control with Git," is quite thorough and well-written. 2 Working with development repositories Every developer creates an instance of a Git repository in his or her own code development directory, updating the repository contents when appropriate by issuing commits. You can have multiple Git repositories. 2.1 Create a repository 2.1.1 Populate your development directory You populate your development directory in the usual manner, say, by using tar to unpack an existing code archive. In this example I have an existing tarball that creates files in a new directory src: $ tar zxf src.tgz $ cd src $ ls . chkcrlf.c hello.c reverse.c trcsg.c .. count.c hn.c ssq.c untrcsg.c ascii.c countnonasc.c home.c ssq2.c usleep.c att.c crush.c ll.c stack.c ut.c attv.c csv.c loop.c tbd.c vtp.c attw.c ctp.c pghack.c tde.c xkey.c bold.c dosify.c pghack2.c thr.c calen.c fixfls.c pghack3.c ticker.c cctime.c fpri.c pghack4.c titleb.c chad.c gib.c pi.c tr2htmlcsg.c 2.1.2 Create a repository Create a repository for this working directory: $ git init Initialized empty Git repository in /Users/cja/src/ $ ls . chad.c gib.c pi.c tr2htmlcsg.c .. chkcrlf.c hello.c reverse.c trcsg.c .git count.c hn.c ssq.c untrcsg.c ascii.c countnonasc.c home.c ssq2.c usleep.c att.c crush.c ll.c stack.c ut.c attv.c csv.c loop.c tbd.c vtp.c attw.c ctp.c pghack.c tde.c xkey.c bold.c dosify.c pghack2.c thr.c calen.c fixfls.c pghack3.c ticker.c cctime.c fpri.c pghack4.c titleb.c Git has created a directory .git, in which it keeps all of its metadata, while it leaves your other files alone. 2.1.3 Establish your identity In Git, all changes you make are identified with your user name and email address. Git tries to determine them automatically, but they will usually be wrong on Windows systems. Specify them yourself: git config user.name "John Q Public" git config user.email "jqp@example.com" Of course, use your own values. If you get "git: command not found," now would be a good time to install Git as described in Section 1 :-). If you forget this step, don't worry. You can correct these values after your first commit, as shown below. 2.2 Populate your repository "Git init" creates an empty repository. You have to put the initial versions of your files into it, first by adding all the files to a "staging area," and then by committing the files from the staging area into the repository. This two-step process is quite powerful, but you can ignore the staging area for now. 2.2.1 Stage the files: $ git add . Here "." means the current directory, so all files in the src directory are added. If you want to see what has been done, type $ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached ..." to unstage) # # new file: ascii.c # new file: att.c # new file: attv.c # new file: attw.c # new file: bold.c # new file: calen.c # new file: cctime.c # new file: chad.c # new file: chkcrlf.c # new file: count.c # new file: countnonasc.c # new file: crush.c # new file: csv.c # new file: ctp.c # new file: dosify.c # new file: fixfls.c # new file: fpri.c # new file: gib.c # new file: hello.c # new file: hn.c # new file: home.c # new file: ll.c # new file: loop.c # new file: pghack.c # new file: pghack2.c # new file: pghack3.c # new file: pghack4.c # new file: pi.c # new file: reverse.c # new file: ssq.c # new file: ssq2.c # new file: stack.c # new file: tbd.c # new file: tde.c # new file: thr.c # new file: ticker.c # new file: titleb.c # new file: tr2htmlcsg.c # new file: trcsg.c # new file: untrcsg.c # new file: usleep.c # new file: ut.c # new file: vtp.c # new file: xkey.c # This shows all the files that will be put in your repository, as well as giving you a command you can type if you want to undo your add step entirely. 2.2.2 Commit the staged files Type "git commit" to commit your staged files to the repository. You will be placed into an editor positioned at the top of a file that looks very much like it was generated by the "git status" command above. By convention, you should enter a one-line summary of changes here, and then a blank line and a more detailed description if necessary. As this is the initial commit, it is sufficent to enter something like "Initial commit.", then save and exit from the editor. Alternatively, for short descriptions, you can append the summary directly to the git commit command, and you won't be put in an editor: $ git commit -m 'Initial commit.' [master (root-commit) 82ba5c4] Initial commit. Committer: Charles Antonelli Your name and email address were configured automatically based on your username and hostname. Please check that they are accurate. You can suppress this message by setting them explicitly: git config --global user.name "Your Name" git config --global user.email you@example.com If the identity used for this commit is wrong, you can fix it with: git commit --amend --author='Your Name ' 44 files changed, 3547 insertions(+), 0 deletions(-) create mode 100644 ascii.c create mode 100644 att.c create mode 100644 attv.c create mode 100644 attw.c create mode 100644 bold.c create mode 100644 calen.c create mode 100644 cctime.c create mode 100644 chad.c create mode 100644 chkcrlf.c create mode 100644 count.c create mode 100644 countnonasc.c create mode 100644 crush.c create mode 100644 csv.c create mode 100644 ctp.c create mode 100644 dosify.c create mode 100644 fixfls.c create mode 100644 fpri.c create mode 100644 gib.c create mode 100644 hello.c create mode 100644 hn.c create mode 100644 home.c create mode 100644 ll.c create mode 100644 loop.c create mode 100644 pghack.c create mode 100644 pghack2.c create mode 100644 pghack3.c create mode 100644 pghack4.c create mode 100644 pi.c create mode 100644 reverse.c create mode 100644 ssq.c create mode 100644 ssq2.c create mode 100644 stack.c create mode 100644 tbd.c create mode 100644 tde.c create mode 100644 thr.c create mode 100644 ticker.c create mode 100644 titleb.c create mode 100644 tr2htmlcsg.c create mode 100644 trcsg.c create mode 100644 untrcsg.c create mode 100644 usleep.c create mode 100644 ut.c create mode 100644 vtp.c create mode 100644 xkey.c This shows that 44 files jointly containing 3547 lines that have been committed to your repository, as well as some instructions at the top for fixing your name and email address if that is needed. You can use "git log" to see what has been done: $ git log commit 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 Author: Charles Antonelli Date: Fri Oct 15 11:50:35 2010 -0400 Initial commit. That long number 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 is a hash, and is used by Git to figure out if two files (or directories, or entire respositories) contain identical contents. You sometimes have to type in these hashes, although Git mostly tries to avoid this. 2.3 Working in your development directory 2.3.1 Committing changes You can edit files in your development directory, compile, test, and so forth, as usual. When you have a set of changed files you would like to commit to the repository, type, say: $ git add csv.c $ git commit -m 'Added note on reuse.' [master 5864bf8] Added note on reuse. Committer: Charles Antonelli 1 files changed, 2 insertions(+), 0 deletions(-) You can have multiple files on the git add command, to commit related changes together. Now git log shows: $ git log commit 5864bf89e42ea0378fba11246cc121030ef76b9f Author: Charles Antonelli Date: Fri Oct 15 12:17:57 2010 -0400 Added reuse heading. commit 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 Author: Charles Antonelli Date: Fri Oct 15 11:50:35 2010 -0400 Initial commit. To see a diff of the changes, type: $ git show commit 5864bf89e42ea0378fba11246cc121030ef76b9f Author: Charles Antonelli Date: Fri Oct 15 12:17:57 2010 -0400 Added reuse heading. diff --git a/csv.c b/csv.c index e59bd0f..7b0eacc 100644 --- a/csv.c +++ b/csv.c @@ -1,3 +1,5 @@ +// this is a classic example of code re-use + #include #include #include This shows that the change consisted of adding two lines at the top of the file. You can also give a commit number: $ git show 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 As this is the commit number of the initial commit, this command will list every line of every file added in the initial commit. 2.3.2 Undoing a commit If you want to undo the most recent commit, while leaving the changes you made to the files in your working tree, enter: $ git reset --soft HEAD^ $ git log commit 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 Author: Charles Antonelli Date: Fri Oct 15 11:50:35 2010 -0400 Initial commit. The commit has disappeared. NOTE: the file remains as you changed it in your working directory; only the repository copy has been reverted to the previous version. To revert the working directory version as well, type instead: $ git reset --hard HEAD^ Be careful with --hard: it will wipe out all of your uncommitted work in your working directory; be very sure that is what you want. 2.3.3 Adding files You can add a new file by: $ vi new.c $ git add new.c $ git commit -m 'Collected transport functions.' You can also create new directories and subdirectories to put new files into. Git handles this automatically. 2.3.4 Removing files You can remove a file by: $ git rm new.c $ git commit -m 'Didn't want this after all.' 2.3.5 Renaming files You can rename a file by: $ git mv new.c bang.c $ git commit -m 'Wanted a more onomatopoetic name.' 2.3.5 Retrieving a committed file Sometimes it is useful to restore a single file or set of files from a given commit. You can do this by, e.g., $ git checkout 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 tde.c ctp.c This restores the contents of the files tde.c and ctp.c from the commit identified by the hash 82ba5c4fc42c937c3b8e2b0ebc5813d5bc5d7c80 to your working directory, overwriting any version of those files already there. 3 Working with depots "Depot" is Git-speak for an authoritative master repository. It is a "bare" repository, Git-speak for a repository that is not intended to be used directly by developers --its only purpose is to serve as the authoritative repository from which developers will pull code into their own repositories, and push code or patches back into for others to use. 3.1 Create a depot A depot is usually created by copying a regular development repository's contents into it. This is called "cloning." By convention, a bare repository is given a ".git" extension: $ cd ~ $ mkdir depot $ cd depot $ git clone --bare ~/src src.git Cloning into bare repository src.git... done. $ cd src.git $ ls . branches hooks packed-refs .. config info refs HEAD description objects This clones the development directory ~/src into bare (depot) directory ~/depot/src.git. Note that some Git metadata has been created in the depot directory, but no files appear there. The files have been copied into the depot repository, however. 3.2 Clone from the depot Here's how to create a clone of a depot repository on any machine on which git is installed. You need to know the hostname on which the depot is stored (here "smartstructure.engin.umich.edu") and the pathname from the root of the host's filesystem to where the depot is stored (here "/Users/cja/depot/src"): $ cd ~ $ mkdir gitwork $ cd gitwork $ git clone ssh://smartstructure.engin.umich.edu/Users/cja/depot/src Cloning into src... Password: remote: Counting objects: 61, done. remote: Compressing objects: 100% (54/54), done. remote: Total 61 (delta 12), reused 0 (delta 0) Receiving objects: 100% (61/61), 28.75 KiB, done. Resolving deltas: 100% (12/12), done. This creates a clone of the depot repository in ~/gitwork: $ ls . .. src $ ls src . chad.c gib.c pghack4.c titleb.c .. chkcrlf.c hello.c pi.c tr2htmlcsg.c .git count.c hn.c reverse.c trcsg.c ascii.c countnonasc.c home.c ssq.c untrcsg.c att.c crush.c ll.c ssq2.c usleep.c attv.c csv.c loop.c stack.c ut.c attw.c ctp.c new.c tbd.c vtp.c bold.c dosify.c pghack.c tde.c xkey.c calen.c fixfls.c pghack2.c thr.c cctime.c fpri.c pghack3.c ticker.c 3.3 Working in the clone repository You can work in the clone repository in the usual way, e.g., using 'git add' and 'git commit' to make changes. There are two common scenarios you will need to keep track of if multiple develoeprs are working in the same repository. 3.3.1 Updating your repository with others' changes In order to update your clone from the depot, to pick up changes that other developers are making, you should: $ git pull This will copy any changes from the depot to your local repository. Other files in your repository and working directory will be left alone. NOTE: If other developers have made changes that conflict with changes you have made to your local repository, the pull operation will create in your local repository a merged copy of each file in which conflicts exist, with all sets of conflicting changes annotated in each file. Here's how conflicts are annotated: [...] <<<<<<< HEAD foo ======= bar baz >>>>>>> 5a20364e41efd51756b837d4e898b890cd2fd87c [...] (Here one version of a file contains the line "foo'" in the same place where the other version contains the lines "bar" and "baz".) You will then have to edit each file to resolve the conflicts, and then push the changes back to the depot [1]. 3.3.2 Updating the depot with your changes In order to update the depot from your clone, to let other developers see your changes, you should: $ git push This will copy your changes to the depot. NOTE: If other developers have made changes that conflict with changes you have made to your local repository, the push operation will fail. You should perform a git pull operation and merge all changes in your local repository, as described in Section 3.3.1, before attempting another git push. 4 Working with branches Branches in Git allow you to start a separate line of development from an arbitrary commit in a repository. Development activity and commit operations proceed entirely independently in each branch. A branch can later be merged with another branch, perhaps the branch it was started from, or it can continue independently of any other branch. When you create a new repository, a default branch named "master" is created for it. We have been implictly using the master branch in the preceding material. 4.1 Preliminaries Let's create another local copy of the source repository: $ cd ~ $ mkdir gitwork2 $ cd gitwork2 $ git clone ssh://smartstructure.engin.umich.edu/Users/cja/depot/src Cloning into src... $ cd src $ git branch * master The git branch command lists all the branches in your repository, with a * next to the current one. Right now we have only the master, and it is the current branch. $ git log --pretty=oneline 265c0045eec3912806575d788d4013abad9b39be Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) 2ca1a6438eacca319507a15b8b56b0f41d0eab83 second version 5a20364e41efd51756b837d4e898b890cd2fd87c a newer file. b0f61391b1abb4bbbf5a42dd7bcdb651bec333b8 Merge branch 'master' of ssh://smartstructure/Users/cja/depot/src b226db6bcb125409d05cad6f0359a07ebac2a853 change 2 from cee-moritz efcd88f5a1602665acc6b6a29093d5f157ddfc01 change 1 from css-max 6c16902e0a22941f8fdedb4e6b5bbb2b6da640dd done on cee-moritz 59334080d2ab7f1fc1a004785f907d1435db71fb a new file af4b6b682b7153b823644b00f20e137c38314e6f Initial commit. Here the "--pretty=oneline" restricts each commit to a single line. The hexadecimal numbers are the ID's of the commits that have been done on the master branch. The tip of the current branch is always labeled HEAD, e.g. $ git log -1 pretty=oneline HEAD 265c0045eec3912806575d788d4013abad9b39be Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) This shows the most recent commit at the end of the current branch. The "-1" argument means show only that one commit. $ git log --pretty=oneline HEAD~1..HEAD 265c0045eec3912806575d788d4013abad9b39be Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) 5a20364e41efd51756b837d4e898b890cd2fd87c a newer file. This shows the most recent commit (named HEAD~1) and the most recent commit. Conventionally, Git counts commits backwards from the HEAD using the "HEAD~n" notation. There is no way to reference the first commit of a branch directly. You can assign an arbitrary name to a commit by tagging it: $ git tag -m"Base version 1.0" V1.0 6c16902e0a22941f8fdedb4e6b5bbb2b6da640dd Now you can refer to that commit using the tag: $ git log --pretty=oneline V1.0 0a22941f8fdedb4e6b5bbb2b6da640dd done on cee-moritz 59334080d2ab7f1fc1a004785f907d1435db71fb a new file af4b6b682b7153b823644b00f20e137c38314e6f Initial commit. This shows the "done on cee-moritz" commit. As "-1" was not specified, if shows all older commits as well. 4.2 Creating a branch To create a new branch, type: $ git branch mynewbranch V1.0 $ git branch * master mynewbranch So we have a new branch, but master is still the current branch. NOTE: branch names can be hierarchically structured, e.g. new/foo, new/foo2, new/bar, etc. This allows wildcards to be used when referencing multiple branches, e.g. new/f* gets all the foos. To see the branch structure, use show-branch: $ git show-branch * [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) ! [mynewbranch] done on cee-moritz -- - [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) * [master^2] a newer file. * [master^] second version * [master~2^2] change 1 from css-max * [master~3] change 2 from cee-moritz *+ [mynewbranch] done on cee-moritz The two lines above the "--" show the two branches in the repository (master and mynewbranch) along with the last commit on each. A * here means this is the head of the current branch (as master is the current branch) and a ! means it is the head of some other branch (as mynewbranch is not the current branch). The branches thus form two columns each headed by their ! or * character. The lines below the "--" show commits on the two branches; a + in the a column indicates that that branch contains this commit, and a blank indicates it does not. A merge commit is shown with a -; a commit on the current branch is shown with a *. So "done on cee-moritz" is present in both branches, which the master branch contains a lot of other commits [2]. 4.3 Working in a branch We can switch the current branch to the root: $ git checkout mynewbranch Switched to branch 'mynewbranch' $ git branch master * mynewbranch Showing the branch contents again: $ git show-branch ! [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) * [mynewbranch] done on cee-moritz -- - [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) + [master^2] a newer file. + [master^] second version + [master~2^2] change 1 from css-max + [master~3] change 2 from cee-moritz +* [mynewbranch] done on cee-moritz We see that our new branch is current, and the only commit on it is "done on cee-moritz". We can work on this branch in the usual manner: $ vi stack.c When ready to commit: $ git add stack.c git commit [mynewbranch 662c57c] Added a header comment. 1 files changed, 2 insertions(+), 0 deletions(-) Showing the branch contents shows the new commit on mynewbranch: $ git show-branch ! [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) * [mynewbranch] Added a header comment. -- * [mynewbranch] Added a header comment. - [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) + [master^2] a newer file. + [master^] second version + [master~2^2] change 1 from css-max + [master~3] change 2 from cee-moritz +* [mynewbranch^] done on cee-moritz Let's make another modification: $ vi loop.c $ git commit -a -m'Added another useful comment.' [mynewbranch f83da24] Added another useful comment. 1 files changed, 1 insertions(+), 0 deletions(-) $ git show-branch ! [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) * [mynewbranch] Added another useful comment. -- * [mynewbranch] Added another useful comment. * [mynewbranch^] Added a header comment. - [master] Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) + [master^2] a newer file. + [master^] second version + [master~2^2] change 1 from css-max + [master~3] change 2 from cee-moritz +* [mynewbranch~2] done on cee-moritz Here the "-a" option to commit tells Git to commit all files in the working directory that are different with respect to the repository versions. In other words, it combines the staging and commit steps. 4.4 Merging a branch At some point we might wish to merge a branch with another. This is done by checking out the target branch and then merging the other branch into it. For example, if you wish to merge mynewbranch back into the master branch: $ git checkout master Switched to branch 'master' $ git merge mynewbranch Merge made by recursive. loop.c | 1 + stack.c | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) Looking at the new branch structure: $ git show-branch * [master] Merge branch 'mynewbranch' ! [mynewbranch] Added another useful comment. -- - [master] Merge branch 'mynewbranch' *+ [mynewbranch] Added another useful comment. What happened to the rest of the structure? By default, Git only shows branch commits back to the nearest common commit. (After the merge, this latest commit is in both branches.) If we want to see it all, specify a count: $ git show-branch --more=10 * [master] Merge branch 'mynewbranch' ! [mynewbranch] Added another useful comment. -- - [master] Merge branch 'mynewbranch' *+ [mynewbranch] Added another useful comment. *+ [mynewbranch^] Added a header comment. * [master^^2] a newer file. * [master~2] second version * [master~3^2] change 1 from css-max * [master~4] change 2 from cee-moritz *+ [master~5] done on cee-moritz *+ [master~6] a new file *+ [master~7] Initial commit. 4.5 Viewing the commit graph The commit graph is a bit difficult to visualize using show-branch. The git log command can show a bit of ascii art: $ git log --graph --pretty=oneline --abbrev-commit * 6f0d07e Merge branch 'mynewbranch' |\ | * f83da24 Added another useful comment. | * 33c1a9f Added a header comment. * | 265c004 Merge branch 'master' of /Users/cja/devel2/../depot/src (had to manually patch newer.c to resolve conflicts within it) |\ \ | * | 5a20364 a newer file. * | | 2ca1a64 second version |/ / * | b0f6139 Merge branch 'master' of ssh://smartstructure/Users/cja/depot/src |\ \ | * | efcd88f change 1 from css-max | |/ * | b226db6 change 2 from cee-moritz |/ * 6c16902 done on cee-moritz * 5933408 a new file * af4b6b6 Initial commit. (Here "--abbrev-commit" shows only enough of those long hexadecimcal IDs so that every abbreviated ID is unique.) The latest commit, i.e. the merged branch) is at the top, with the master branch on the left and mynewbranch on the right. When installing msysGit a GUI tool called gitk is also installed. This tool is very useful for showing the above diagram in a more readily understandable way. You can also easily show differences between any two commits. You invoke it as follows: $ cd /my/local/repository $ gitk Using gitk, it is easier to see that the mynewbranch branch sprouted from the "done on cee-moritz" branch and added the two "header comment" commits, before merging back with the master. The other complexity on the master is shown to be two separate instances where incompatible changes were made to the same file, which was immediately resolved in each case. 4.6 Pushing back to the depot After creating, working with, and merging the branch, we can push the repository back to the depot: $ git push Password: Counting objects: 12, done. Delta compression using up to 16 threads. Compressing objects: 100% (7/7), done. Writing objects: 100% (8/8), 865 bytes, done. Total 8 (delta 4), reused 0 (delta 0) To ssh://smartstructure.engin.umich.edu/Users/cja/depot/src 265c004..6f0d07e master -> master Now the depot contains the new branch. Another developer can pull the updates from the depot including the new branch into his or her local repository in the usual way: $ cd mygit2 $ git pull remote: Counting objects: 12, done. remote: Compressing objects: 100% (7/7), done. remote: Total 8 (delta 4), reused 0 (delta 0) Unpacking objects: 100% (8/8), done. From /Users/cja/devel2/../depot/src 265c004..6f0d07e master -> origin/master Updating 265c004..6f0d07e Fast-forward loop.c | 1 + stack.c | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) $ git log --graph --pretty=oneline --abbrev-commit git log --graph --pretty=oneline --abbrev-commit * 6f0d07e Merge branch 'mynewbranch' |\ | * f83da24 Added another useful comment. | * 33c1a9f Added a header comment. * | 265c004 Merge branch 'master' of /Users/cja/devel2/../depot/src (had to ma |\ \ | * | 5a20364 a newer file. * | | 2ca1a64 second version |/ / * | b0f6139 Merge branch 'master' of ssh://smartstructure/Users/cja/depot/src |\ \ | * | efcd88f change 1 from css-max | |/ * | b226db6 change 2 from cee-moritz |/ * 6c16902 done on cee-moritz * 5933408 a new file * af4b6b6 Initial commit. Footnotes [1] Of course, the second push will fail if someone else has pushed conflicting changes to the repository after you performed the pull. In this case, simply merge and push again. This is okay, and doesn't happen often. [2] Given a commit named C in a commit graph G, C~1 is the first parent of C, C~2 the first grandparent, C^1 is the first parent, and c^2 is the second parent, and so on. These may be combined to address any node in G, e.g. master~2^2 means the second parent of the graph rooted at the master's HEAD. (In Git, the root of the graph is at the bottom, and subordinate nodes are labeled as parents.)