This lecture aims at providing a brief review of some advanced topics in Git Version Control System which are essential for effective management of large collaborative projects.
A useful Git-cheatsheet link for future reference: Advanced Git cheatsheet
This video is created solely as reference for the attendants of ICP2017F course at UT Austin. If you did not attend this class, then you may not find this video useful.
Getting help for Git commands
There are basically three ways to request information about Git commands on the Git-bash command line:
$ git help <command name> $ git <command name> --help $ man git-<command name>
Note that the last command
man is not a Git command. All Git commands begin with the word git.
Viewing the Git commit history
You can check the history of project commits to the repository using the Git command
For example, here is a snippet from the output of
git log on laptop screen:
$ git log commit 264043e0d49006b7f59e57639961c333b5d5f124 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Tue Jan 24 17:48:33 2017 -0600 data tables for 1D model added. commit b45ddd780c18736bac42ff27aade301a6b0f09cb Author: Amir Shahmoradi <email@example.com> Date: Tue Jan 24 10:08:53 2017 -0600 minor edit commit b6f4fb69d97a396bde7159c78424100704328634 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Thu Jan 12 21:03:28 2017 -0600 *.txt files removed commit 961ff2d4ac68081a21864b2f1b067b43424d3342 Author: Amir Shahmoradi <email@example.com> Date: Thu Jan 12 21:02:00 2017 -0600 update commit 8fd3c49e90d96f4bcef2302c7b227f06ad7a5250 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Thu Jan 12 19:36:45 2017 -0600 minor commit cd0ed7def385ba29ea134bcc18a4ad0873d9f5ee Author: Amir Shahmoradi <email@example.com> Date: Thu Jan 12 19:32:51 2017 -0600 minor commit 8096668868ef64189f788669d5f1838cd944f9b6 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Thu Jan 12 19:28:22 2017 -0600 minor commit c52ba6adea474625cce1493896ecaac40cb976af Author: Amir Shahmoradi <email@example.com> Date: Thu Jan 12 19:24:23 2017 -0600 minor commit ab5a17f9e913e55cae0f971fd9b485a0a6e8dec3 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Thu Jan 12 19:16:27 2017 -0600 minor commit ce5c2421db6e76a338a0e6922acead9100a7c4c4 Author: Amir Shahmoradi <email@example.com> Date: Thu Jan 12 19:10:19 2017 -0600 minor commit 4a7d27d81260c2e2a29b6259e6c97befc065c069 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Thu Jan 12 19:05:14 2017 -0600 :
There is a long list of options that can be used with
git log command to display exactly what you need on bash screen.
Some of the most useful are discussed below.
To lists the differences of the files between different commits use
$ git log -p
To lists only a limited number of most recent commits use
-<number of commits to display> flag. For example:
$ git log -2 $ git log -2 commit 264043e0d49006b7f59e57639961c333b5d5f124 Author: Amir Shahmoradi <email@example.com> Date: Tue Jan 24 17:48:33 2017 -0600 data tables for 1D model added. commit b45ddd780c18736bac42ff27aade301a6b0f09cb Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Tue Jan 24 10:08:53 2017 -0600 minor edit
To list the statistics of the commits, use,
$ git log --stat -1 commit 264043e0d49006b7f59e57639961c333b5d5f124 Author: Amir Shahmoradi <email@example.com> Date: Tue Jan 24 17:48:33 2017 -0600 data tables for 1D model added. README.md | 1 + results/tables/README.md | 8 ++- results/tables/tgm.mat | Bin 0 -> 2550889 bytes src/defineProject.m | 3 +- src/main.m | 82 +++++++++------------------ src/writeTables.m | 75 ++++++++++++++++++++++++ 9 files changed, 140 insertions(+), 56 deletions(-)
The log data can be even represented formatted via the flag
--pretty=format:"<the desired format>". For example,
$ git log -3 --pretty=format:"%h - %an, %ar : %s" 264043e - Amir Shahmoradi, 7 days ago : data tables for 1D model added. b45ddd7 - Amir Shahmoradi, 7 days ago : minor edit b6f4fb6 - Amir Shahmoradi, 3 weeks ago : *.txt files removed
A list of available format options is provided below.
|Option||Description of Output|
||Abbreviated commit hash|
||Abbreviated tree hash|
||Abbreviated parent hashes|
||Author date (format respects the --date=option)|
||Author date, relative|
||Committer date, relative|
A list of useful options for
git log is given in the table below.
||Show the patch introduced with each commit.|
||Show statistics for files modified in each commit.|
||Display only the changed/insertions/deletions line from the --stat command.|
||Show the list of files modified after the commit information.|
||Show the list of files affected with added/modified/deleted information as well.|
||Show only the first few characters of the SHA-1 checksum instead of all 40.|
||Display the date in a relative format (for example, “2 weeks ago”) instead of using the full date format.|
||Display an ASCII graph of the branch and merge history beside the log output.|
||Show commits in an alternate format. Options include oneline, short, full, fuller, and format (where you specify your own format).|
A list of useful options for
git log commands that can change the format of the output, is given in the table below.
||Show only the last n commits (e.g., -2, -3, ...).|
||Limit the commits to those made after the specified date.|
||Limit the commits to those made before the specified date.|
||Only show commits in which the author entry matches the specified string.|
||Only show commits in which the committer entry matches the specified string.|
||Only show commits with a commit message containing the string.|
||Only show commits adding or removing code matching the string.|
For example, to list the commit history since a specific time in the past, use
$ git log --since=2.weeks commit 264043e0d49006b7f59e57639961c333b5d5f124 Author: Amir Shahmoradi <firstname.lastname@example.org> Date: Tue Jan 24 17:48:33 2017 -0600 data tables for 1D model added. commit b45ddd780c18736bac42ff27aade301a6b0f09cb Author: Amir Shahmoradi <email@example.com> Date: Tue Jan 24 10:08:53 2017 -0600 minor edit
or, with the following date format:
$ git log --since="2017-01-15"
Undoing, amending, and tagging
Suppose you want to undo the latest addition of files to the stage area. The command to use in order to clean the stage area is,
$ git reset
This command is basically the opposite of
git add. There are a lot of options that can accompany this Git command, details of which can be found in Git documentation.
However, be careful when using this command, especially with flag
--hard, which can result in changes in your working directory as well, thus leading to involuntary loss of latest uncommitted files.
Another useful command is,
$ git commit --amend
which is used when you forget to add some files to your latest commit and now, you would like to add the latest content of your project’s staging area to the last commit, by amending it.
The Git command
git tag allows you to tag specific important commits in your commit history, for example a final release of your project/software. If you just type
git tag on Git bash command line, it will list all tags in the project, in alphabetical order,
$ git tag v1.0 v1.1 v2.0
You can create a tag for the latest commit to your repository by using,
git tag -a v3.0 -m "new version of project"
This will add a new tag pointing to the latest commit in the project with name
v3.0 and the message new version of project.
Now if you want to display the information about a specific tag, use
$ git show v1.0 tag v1.0 Tagger: Amir Shahmoradi <firstname.lastname@example.org> Date: Tue Jan 1 18:08:00 2017 -0600 first tag commit 25129a074aece69d234838764e7df63ed1fb3023 Author: Amir Shahmoradi <email@example.com> Date: Fri Dec 27 17:12:08 2016 -0600 Update README.md
You can also create a lightweight tag by avoiding
-m flags in you tag command,
git tag v4.0
Annotated tags (created with
-a flag) are meant for very important project versions, such as a software release, while lightweight tags are meant for private or temporary object labels.
For more information about
git tag, see Git documentation.
Working with remote Repositories
In order to see which remote servers you have configured for your project, you can run the following Git command,
$ git remote origin
In the output above,
origin is the default name that Git gives to the server you cloned your project from. If you also specify
-v flag, Git will show you the URLs that Git has stored for the remote shortname (e.g., origin) to be used when reading and writing to that remote repository.
$ git remote -v origin firstname.lastname@example.org:shahmoradi/foo.git (fetch) origin email@example.com:shahmoradi/foo.git (push)
In order to see more information about a particular remote repository in your project, you can use,
$ git remote show origin * remote origin Fetch URL: firstname.lastname@example.org:shahmoradi/foo.git Push URL: email@example.com:shahmoradi/foo.git HEAD branch: master Remote branches: development tracked master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
The above information indicates that the current HEAD branch of the project is on master branch, and the remote branches on the remote repository are master and development.
You can find more information about
git remote command in Git documentation.
Branching is powerful idea in Version Control Systems, which significantly facilitates collaboration or parallel development of a project. Suppose you have already a project which has reached its first release version, meaning that it works all fine. Now, you like to add a new feature to your project. To do this and to avoid further commits to your original project, you can create a new branch of the project which is specifically devoted to adding the new feature. See the following figure, for an example of Git branching.
When you create a Git project, the default single branch in your project is master. So, for example if you search for your project branches, you’d see,
$ git branch * master
If you already have created other branches in your project, for example development, then you may see a Git message like the following,
$ git branch * development master
The * behind the branch name indicates that the project HEAD (i.e., your working directory) points to that branch, that is, all commits will be made to that branch that is highlighted with *. In the example above, the working directory points to development branch.
In order to create a new branch in your project, use,
$ git branch <branch name>
$ git branch development
When you create a new branch, Git creates an exact duplicate of the current branch that you are in, but with the requested name for the new branch. In order to switch to a specific Git branch in your project, use,
$ git checkout <branch name>
$ git checkout development Switched to branch 'development'
A shortcut for both creating a new branch from the current branch, and switching to the new branch automatically is to use,
$ git checkout -b <branch name>
$ git checkout -b test Switched to a new branch 'test'
Now suppose, you have made some significant progress on your project development branch, and now you want to add the newly developed feature to your master branch. All you need to do, is,
$ git checkout master $ git merge development
By doing this, you first switch to master branch, then request Git, to merge all changes made to the project on the development branch to be copied and transferred to the master branch. For example, if I have added a single
test.txt file, and committed the change to the development branch, then upon mergin with master, Git will display something like the following,
$ git merge development Updating 25129a0..57ed7c2 Fast-forward test.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 test.txt
Now suppose there was no change in the development branch, since branching it from master. Then upon merging, you would get a message like the following,
$ git merge development Already up-to-date.
Occasionally, conflicts may arise between branches upon merging. This happens when a common file between the two branches, has been modified on both branches in parallel. In such cases, you will need to resolve the conflict by choosing one of the file edits in one of the branches and discard the other. The following is an example merge conflict message by Git.
$ git merge development Auto-merging test.txt CONFLICT (content): Merge conflict in test.txt Automatic merge failed; fix conflicts and then commit the result.
For example, if you use
git status command, the following is the typical message that will be displayed,
$ git status On branch test You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: test.txt no changes added to commit (use "git add" and/or "git commit -a")
To resolve the conflict, open the conflicting file. There you will see the segments of the file from both versions which are the cause of the conflict. Edit the file as you wish. and then perform the normal
git add and
git commit on the file, to resolve the conflict and complete the merge process.
In addition to
git merge, there is another more elegant and powerful Git command,
git rebase for integrating changes in different branches into a single branch. But, the subject goes beyond the goals of this class, and the interested reader is referred to Git documentation for this command and this pedagogical Git page for
Deleting a branch
Normally, when a branch merge is done, the development branch is not needed anymore, so it is always wise and cleaner to delete the unwanted branches, using the command
git branch -d <branch name>. To do this, on the same branch that you just performed
git merge use,
$ git checkout master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Switched to branch 'master' $ git branch -d test Deleted branch hotfix (3a0874c).
Note that you cannot delete a branch while you are on it (i.e., while it is checked out). For example, Git will give you the following error message,
$ git branch -d test error: Cannot delete branch 'test' checked out at 'C:/Users/Amir/git/foo'
You cannot delete a branch from another branch with which you have not performed the merging either. In this case, Git will give the following error,
$ git branch -d test error: The branch 'test' is not fully merged. If you are sure you want to delete it, run 'git branch -D test'.
Advice for good project management
Your master branch should always contain the latest clean version of your project, that is, the complete and working version/release. You should always make your new developments in a separate branch, and once it works and the new feature/development is complete, you merge the new development into the master branch.