Skip to content
Eric Bouchut edited this page Jun 20, 2016 · 61 revisions

Commit

In this section

  • <commit-ish> denotes any revision that refers to a commit. To learn more, read this.

How to write a git commit message

View the diff of changes while editing the commit message

git commit -v

The option -v of git commit launches the editor with the usual list of modified files plus the difference (git diff) below, so that you can take a look at the changes while writing the commit message. Do not worry the diff is not part of the commit message when you save the file.

Cherry-Pick a commit and replay it on the current branch

git cherry-pick  1234567

Add the commit with the SHA1 1234567 to the tip of the current branch. The new commit has the same commit message and modification but a different SHA1, date.

Cherry-Pick multiple commits

Assuming we want to pick the commits a, b, c (ordered by date) to rebase them on the current branch.

git log -3 c   # ordered by reverse chronological order (most recent first) 
  c
  b
  a

Here is how to do this.

git cherry-pick  a^..c

Add the commits from SHA1 a up to and including c to the tip of the current branch. Commit a must be older than c.

FYI, a..c denotes the commits b and c, that is from a (not included) up to and including c. This is why I append a caret after a to make sure it is included in the range.

Generate a patch for a commit

  • Generate a patch file for a commit (say the commit with the SHA1 1234567 for instance).
git format-patch -1  1234567 --output - > file.patch
  • Apply the patch
# Show patch stats
  git apply --stat file.patch

# Check for error before applying 
  git apply --check file.patch 

# Apply the patch
  git am < file.patch

Change the author e-mail of the most recent commit

This may be useful when the very last commit does not contain the correct (user name or) user email because you made a commit with the wrong user name and/or email. This can be changed provided you did not pushed the commit a remote repository.

Say for instance, I have on my computer both personal and corporate repositories. I need to use a distinct e-mail address for each kind:

I configured user.email and/or user.email globally with my personal name and email address like so.

git config --global user.name "Eric Bouchut"
git config --global user.email eric@perso.example.org

Then I clone a corporate repository, commit a change. I notice immediately after while running git log that I forgot to set my corporate e-mail address (eric@corp.example.com) for this project.

git log -1

commit 3c7abd382b653fc58f3ca890f220cb4de9adb65a
Author: Eric Bouchut <eric@perso.example.org>
Date:   Fri Mar 4 14:45:18 2016 +0100                                                                  │
Change settings

The last commit (git log -1) contains my personal email address eric.perso.example.org instead of the corporate one eric@corp.example.com!

Assuming I did not pushed this commit to any remote repository, here how to fix this. First, when in the repository I set my corporate e-mail address for this corporate repository.

# cd into the repository beforehand
#
# git config user.name "Eric Bouchut"
git config user.email eric@corp.example.com  

I then fix the author name and email of the very last commit, like so

git commit --amend --reset-author --no-edit

The option --amend asks git to change the most recent commit, --no-edit left the commit message unchanged and --reset-author replaces the author user name and e-mail address with the one in the local git configuration, that is Eric Bouchut <eric@corp.example.com>. The above command basically does the same thing as:

git commit --amend --no-edit --author "Eric Bouchut <eric@corp.example.com>" 

This is now fixed, as I can see the email address changed.

git log -1

commit 77f5b4bd0f7813379dd9a2f6d8d2658a55e9cadc
Author: Eric Bouchut <eric@corp.example.com>
Date:   Fri Mar 4 14:49:01 2016 +0100                                                                  │
Change settings

Cancel the current commit while editing the commit message in vim

Say you are in the middle of editing the commit message in vim, and you want to cancel the commit. Typing :q!<CR> will not prevent the commit from being made. You have two options:

  • Make sure the commit message is empty and save it using :wq<CR>
  • or type :cquit!<CR>

The latter does:

  • not save the file
  • exit with an error code

Git will then figure out vim failed and cancel the commit.

git commit
# You are now in vim typing your commit message 
# and figure out you would like to prevent the commit from being made
# Type this:

:cquit!<CR>

How to refer to a commit

See girevisions(7) and Revisions Selection in the Pro-Git book.

Convert a Ref-name into a SHA1, back and forth

To get the SHA1 that corresponds to a ref-name like master.

# Convert ref-name ==> SHA1
# master ==> ?

git rev-parse master
43dc2f87931f720f348c9a6ab4c67aa825afac18

You can also use this to get the SHA1 of a tag.

To get the list of ref-names that correspond to a SHA1:

# Convert SHA1 ==> ref-name(s)
# 43dc2f87931f720f348c9a6ab4c67aa825afac18 ==> ?

git name-rev --name-only 43dc2f87931f720f348c9a6ab4c67aa825afac18
master

git describe --all --contains 43dc2f87931f720f348c9a6ab4c67aa825afac18
master

Show the content of a file at a given commit

Say you want to see what the file foo/bar/joe looks like at the commit 1234560.

git show 1234560:foo/bar/joe

If you omit the SHA1 commit, HEAD is used instead. HEAD denotes the tip of the current branch, say master if you are on that branch.

git show :foo/bar/joe

# Same as
#   git show HEAD:foo/bar/joe

Retrieve the content of a file at a given commit

Say you want to get the file foo/bar/joe at the commit 1234560.

git checkout 1234560 -- foo/bar/joe

This will overwrite the working copy of the file foo/bar/joe with what it looked like at commit 1234560.

List all the files available at a given commit

git ls-tree --name-only -r <commit-ish>

git ls-tree --name-only -r HEAD

README.md
LICENSE

In the above example, the commit referenced by HEAD contains 2 files README.mdand LICENSE

List the files modified in a commit

git diff-tree --no-commit-id --name-only -r <commit-ish> There is at least two ways to get this:

git diff-tree --no-commit-id --name-only -r  HEAD

  README.md
git log --name-only -1 HEAD

  commit 36718c78caf9247c7dfb81a3844fa2c781bdee17                                                     
  Author: Eric Bouchut <eric@example.com>
  Date:   Mon Jan 26 22:19:49 2015 -0500

    Updated README

  README.md

Here the only file modified in the commit referenced by HEAD is README.md.

Revert to a given commit

I want to restore the working tree to the state it was in at commit 1234560 because what I have done after this commit is either buggy or does not work. I however do not want to rewrite the history by removing commits (1661fc2 and 59e2e45) because I already have pushed them upstream. git revert will undo the modifications up to but not including commit 1234560.

git log --oneline --decorate
  1661fc2 (HEAD, master) New layout engine
  59e2e45 Tweak settings panel
  1234560 Finalize UI
  ...
  3e06842 First commit
  • Ensure you working tree is clean by either ignoring, stashing or committing the files that are not yet in the repository.
  • Revert to the commit 1234560
git revert -n 1234560..HEAD

This modifies the working tree to cancel the changes done after commit 1234560 and up to the tip of the current branch (1661fc2 and 59e2e45). The -n flag asks git revert not to commit the changes which gives us the opportunity to review them.

  • Commit the changes to the repository
git commit -m "Revert to 1234560"

Search for commit by SHA1

To determine if a Git repository contains a commit with a given SHA1 (say 123456 for instance), use the following:

git branch -a --contains 123456   # 123456 is the SHA1 of the commit I'm searching for
 
* search_query
  remotes/origin/search_query

In this example, the branches search_query and origin/search_query contains the commit whose SHA1 is 123456.

Remove a file from the git history

Say you comited a big file or a private file (including passwords...) a while ago. You now want to remove it from the repository so that it no longer exists.

http://stackoverflow.com/a/15729420/386517

Clone this wiki locally