Documentation / howto / revert-branch-rebase.txton commit git-apply: war on whitespace -- finishing touches. (56248c5)
   1From: Junio C Hamano <junkio@cox.net>
   2To: git@vger.kernel.org
   3Subject: [HOWTO] Reverting an existing commit
   4Abstract: In this article, JC gives a small real-life example of using
   5 'git revert' command, and using a temporary branch and tag for safety
   6 and easier sanity checking.
   7Date: Mon, 29 Aug 2005 21:39:02 -0700
   8Content-type: text/asciidoc
   9Message-ID: <7voe7g3uop.fsf@assigned-by-dhcp.cox.net>
  10
  11Reverting an existing commit
  12============================
  13
  14One of the changes I pulled into the 'master' branch turns out to
  15break building GIT with GCC 2.95.  While they were well intentioned
  16portability fixes, keeping things working with gcc-2.95 was also
  17important.  Here is what I did to revert the change in the 'master'
  18branch and to adjust the 'pu' branch, using core GIT tools and
  19barebone Porcelain.
  20
  21First, prepare a throw-away branch in case I screw things up.
  22
  23------------------------------------------------
  24$ git checkout -b revert-c99 master
  25------------------------------------------------
  26
  27Now I am on the 'revert-c99' branch.  Let's figure out which commit to
  28revert.  I happen to know that the top of the 'master' branch is a
  29merge, and its second parent (i.e. foreign commit I merged from) has
  30the change I would want to undo.  Further I happen to know that that
  31merge introduced 5 commits or so:
  32
  33------------------------------------------------
  34$ git show-branch --more=4 master master^2 | head
  35* [master] Merge refs/heads/portable from http://www.cs.berkeley....
  36 ! [master^2] Replace C99 array initializers with code.
  37--
  38-  [master] Merge refs/heads/portable from http://www.cs.berkeley....
  39*+ [master^2] Replace C99 array initializers with code.
  40*+ [master^2~1] Replace unsetenv() and setenv() with older putenv().
  41*+ [master^2~2] Include sys/time.h in daemon.c.
  42*+ [master^2~3] Fix ?: statements.
  43*+ [master^2~4] Replace zero-length array decls with [].
  44*  [master~1] tutorial note about git branch
  45------------------------------------------------
  46
  47The '--more=4' above means "after we reach the merge base of refs,
  48show until we display four more common commits".  That last commit
  49would have been where the "portable" branch was forked from the main
  50git.git repository, so this would show everything on both branches
  51since then.  I just limited the output to the first handful using
  52'head'.
  53
  54Now I know 'master^2~4' (pronounce it as "find the second parent of
  55the 'master', and then go four generations back following the first
  56parent") is the one I would want to revert.  Since I also want to say
  57why I am reverting it, the '-n' flag is given to 'git revert'.  This
  58prevents it from actually making a commit, and instead 'git revert'
  59leaves the commit log message it wanted to use in '.msg' file:
  60
  61------------------------------------------------
  62$ git revert -n master^2~4
  63$ cat .msg
  64Revert "Replace zero-length array decls with []."
  65
  66This reverts 6c5f9baa3bc0d63e141e0afc23110205379905a4 commit.
  67$ git diff HEAD ;# to make sure what we are reverting makes sense.
  68$ make CC=gcc-2.95 clean test ;# make sure it fixed the breakage.
  69$ make clean test ;# make sure it did not cause other breakage.
  70------------------------------------------------
  71
  72The reverted change makes sense (from reading the 'diff' output), does
  73fix the problem (from 'make CC=gcc-2.95' test), and does not cause new
  74breakage (from the last 'make test').  I'm ready to commit:
  75
  76------------------------------------------------
  77$ git commit -a -s ;# read .msg into the log,
  78                    # and explain why I am reverting.
  79------------------------------------------------
  80
  81I could have screwed up in any of the above steps, but in the worst
  82case I could just have done 'git checkout master' to start over.
  83Fortunately I did not have to; what I have in the current branch
  84'revert-c99' is what I want.  So merge that back into 'master':
  85
  86------------------------------------------------
  87$ git checkout master
  88$ git resolve master revert-c99 fast ;# this should be a fast forward
  89Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
  90 cache.h        |    8 ++++----
  91 commit.c       |    2 +-
  92 ls-files.c     |    2 +-
  93 receive-pack.c |    2 +-
  94 server-info.c  |    2 +-
  95 5 files changed, 8 insertions(+), 8 deletions(-)
  96------------------------------------------------
  97
  98The 'fast' in the above 'git resolve' is not a magic.  I knew this
  99'resolve' would result in a fast forward merge, and if not, there is
 100something very wrong (so I would do 'git reset' on the 'master' branch
 101and examine the situation).  When a fast forward merge is done, the
 102message parameter to 'git resolve' is discarded, because no new commit
 103is created.  You could have said 'junk' or 'nothing' there as well.
 104
 105There is no need to redo the test at this point.  We fast forwarded
 106and we know 'master' matches 'revert-c99' exactly.  In fact:
 107
 108------------------------------------------------
 109$ git diff master..revert-c99
 110------------------------------------------------
 111
 112says nothing.
 113
 114Then we rebase the 'pu' branch as usual.
 115
 116------------------------------------------------
 117$ git checkout pu
 118$ git tag pu-anchor pu
 119$ git rebase master
 120* Applying: Redo "revert" using three-way merge machinery.
 121First trying simple merge strategy to cherry-pick.
 122Finished one cherry-pick.
 123* Applying: Remove git-apply-patch-script.
 124First trying simple merge strategy to cherry-pick.
 125Simple cherry-pick fails; trying Automatic cherry-pick.
 126Removing Documentation/git-apply-patch-script.txt
 127Removing git-apply-patch-script
 128Finished one cherry-pick.
 129* Applying: Document "git cherry-pick" and "git revert"
 130First trying simple merge strategy to cherry-pick.
 131Finished one cherry-pick.
 132* Applying: mailinfo and applymbox updates
 133First trying simple merge strategy to cherry-pick.
 134Finished one cherry-pick.
 135* Applying: Show commits in topo order and name all commits.
 136First trying simple merge strategy to cherry-pick.
 137Finished one cherry-pick.
 138* Applying: More documentation updates.
 139First trying simple merge strategy to cherry-pick.
 140Finished one cherry-pick.
 141------------------------------------------------
 142
 143The temporary tag 'pu-anchor' is me just being careful, in case 'git
 144rebase' screws up.  After this, I can do these for sanity check:
 145
 146------------------------------------------------
 147$ git diff pu-anchor..pu ;# make sure we got the master fix.
 148$ make CC=gcc-2.95 clean test ;# make sure it fixed the breakage.
 149$ make clean test ;# make sure it did not cause other breakage.
 150------------------------------------------------
 151
 152Everything is in the good order.  I do not need the temporary branch
 153nor tag anymore, so remove them:
 154
 155------------------------------------------------
 156$ rm -f .git/refs/tags/pu-anchor 
 157$ git branch -d revert-c99
 158------------------------------------------------
 159
 160It was an emergency fix, so we might as well merge it into the
 161'release candidate' branch, although I expect the next release would
 162be some days off:
 163
 164------------------------------------------------
 165$ git checkout rc
 166$ git pull . master
 167Packing 0 objects
 168Unpacking 0 objects
 169
 170* committish: e3a693c...        refs/heads/master from .
 171Trying to merge e3a693c... into 8c1f5f0... using 10d781b...
 172Committed merge 7fb9b7262a1d1e0a47bbfdcbbcf50ce0635d3f8f
 173 cache.h        |    8 ++++----
 174 commit.c       |    2 +-
 175 ls-files.c     |    2 +-
 176 receive-pack.c |    2 +-
 177 server-info.c  |    2 +-
 178 5 files changed, 8 insertions(+), 8 deletions(-)
 179------------------------------------------------
 180
 181And the final repository status looks like this:
 182
 183------------------------------------------------
 184$ git show-branch --more=1 master pu rc
 185! [master] Revert "Replace zero-length array decls with []."
 186 ! [pu] git-repack: Add option to repack all objects.
 187  * [rc] Merge refs/heads/master from .
 188---
 189 +  [pu] git-repack: Add option to repack all objects.
 190 +  [pu~1] More documentation updates.
 191 +  [pu~2] Show commits in topo order and name all commits.
 192 +  [pu~3] mailinfo and applymbox updates
 193 +  [pu~4] Document "git cherry-pick" and "git revert"
 194 +  [pu~5] Remove git-apply-patch-script.
 195 +  [pu~6] Redo "revert" using three-way merge machinery.
 196  - [rc] Merge refs/heads/master from .
 197++* [master] Revert "Replace zero-length array decls with []."
 198  - [rc~1] Merge refs/heads/master from .
 199... [master~1] Merge refs/heads/portable from http://www.cs.berkeley....
 200------------------------------------------------