f627e4271c40fc2c4b28f825828e205b2fc8cb88
   1From:   Junio C Hamano <junkio@cox.net>
   2To:     git@vger.kernel.org
   3Cc:     Petr Baudis <pasky@suse.cz>, Linus Torvalds <torvalds@osdl.org>
   4Subject: Re: sending changesets from the middle of a git tree
   5Date:   Sun, 14 Aug 2005 18:37:39 -0700
   6Abstract: In this article, JC talks about how he rebases the
   7 public "pu" branch using the core GIT tools when he updates
   8 the "master" branch, and how "rebase" works.  Also discussed
   9 is how this applies to individual developers who sends patches
  10 upstream.
  11
  12Petr Baudis <pasky@suse.cz> writes:
  13
  14> Dear diary, on Sun, Aug 14, 2005 at 09:57:13AM CEST, I got a letter
  15> where Junio C Hamano <junkio@cox.net> told me that...
  16>> Linus Torvalds <torvalds@osdl.org> writes:
  17>> 
  18>> > Junio, maybe you want to talk about how you move patches from your "pu" 
  19>> > branch to the real branches.
  20>> 
  21> Actually, wouldn't this be also precisely for what StGIT is intended to?
  22
  23Exactly my feeling.  I was sort of waiting for Catalin to speak
  24up.  With its basing philosophical ancestry on quilt, this is
  25the kind of task StGIT is designed to do.
  26
  27I just have done a simpler one, this time using only the core
  28GIT tools.
  29
  30I had a handful commits that were ahead of master in pu, and I
  31wanted to add some documentation bypassing my usual habit of
  32placing new things in pu first.  At the beginning, the commit
  33ancestry graph looked like this:
  34
  35                             *"pu" head
  36    master --> #1 --> #2 --> #3
  37
  38So I started from master, made a bunch of edits, and committed:
  39
  40    $ git checkout master
  41    $ cd Documentation; ed git.txt git-apply-patch-script.txt ...
  42    $ cd ..; git add Documentation/*.txt
  43    $ git commit -s -v
  44
  45NOTE.  The -v flag to commit is a handy way to make sure that
  46your additions are not introducing bogusly formatted lines.
  47
  48After the commit, the ancestry graph would look like this:
  49
  50                              *"pu" head
  51    master^ --> #1 --> #2 --> #3
  52          \
  53            \---> master
  54
  55The old master is now master^ (the first parent of the master).
  56The new master commit holds my documentation updates.
  57
  58Now I have to deal with "pu" branch.
  59
  60This is the kind of situation I used to have all the time when
  61Linus was the maintainer and I was a contributor, when you look
  62at "master" branch being the "maintainer" branch, and "pu"
  63branch being the "contributor" branch.  Your work started at the
  64tip of the "maintainer" branch some time ago, you made a lot of
  65progress in the meantime, and now the maintainer branch has some
  66other commits you do not have yet.  And "git rebase" was written
  67with the explicit purpose of helping to maintain branches like
  68"pu".  You _could_ merge master to pu and keep going, but if you
  69eventually want to cherrypick and merge some but not necessarily
  70all changes back to the master branch, it often makes later
  71operations for _you_ easier if you rebase (i.e. carry forward
  72your changes) "pu" rather than merge.  So I ran "git rebase":
  73
  74    $ git checkout pu
  75    $ git rebase master pu
  76
  77What this does is to pick all the commits since the current
  78branch (note that I now am on "pu" branch) forked from the
  79master branch, and forward port these changes.
  80
  81    master^ --> #1 --> #2 --> #3
  82          \                                  *"pu" head
  83            \---> master --> #1' --> #2' --> #3'
  84
  85The diff between master^ and #1 is applied to master and
  86committed to create #1' commit with the commit information (log,
  87author and date) taken from commit #1.  On top of that #2' and #3'
  88commits are made similarly out of #2 and #3 commits.
  89
  90Old #3 is not recorded in any of the .git/refs/heads/ file
  91anymore, so after doing this you will have dangling commit if
  92you ran fsck-cache, which is normal.  After testing "pu", you
  93can run "git prune" to get rid of those original three commits.
  94
  95While I am talking about "git rebase", I should talk about how
  96to do cherrypicking using only the core GIT tools.
  97
  98Let's go back to the earlier picture, with different labels.
  99
 100You, as an individual developer, cloned upstream repository and
 101amde a couple of commits on top of it.
 102
 103                              *your "master" head
 104   upstream --> #1 --> #2 --> #3
 105
 106You would want changes #2 and #3 incorporated in the upstream,
 107while you feel that #1 may need further improvements.  So you
 108prepare #2 and #3 for e-mail submission.
 109
 110    $ git format-patch master^^ master
 111
 112This creates two files, 0001-XXXX.txt and 0002-XXXX.txt.  Send
 113them out "To: " your project maintainer and "Cc: " your mailing
 114list.  You could use contributed script git-send-email-script if
 115your host has necessary perl modules for this, but your usual
 116MUA would do as long as it does not corrupt whitespaces in the
 117patch.
 118
 119Then you would wait, and you find out that the upstream picked
 120up your changes, along with other changes.
 121
 122   where                      *your "master" head
 123  upstream --> #1 --> #2 --> #3
 124    used   \ 
 125   to be     \--> #A --> #2' --> #3' --> #B --> #C
 126                                                *upstream head
 127
 128The two commits #2' and #3' in the above picture record the same
 129changes your e-mail submission for #2 and #3 contained, but
 130probably with the new sign-off line added by the upsteam
 131maintainer and definitely with different committer and ancestry
 132information, they are different objects from #2 and #3 commits.
 133
 134You fetch from upstream, but not merge.
 135
 136    $ git fetch upstream
 137
 138This leaves the updated upstream head in .git/FETCH_HEAD but
 139does not touch your .git/HEAD nor .git/refs/heads/master.  
 140You run "git rebase" now.
 141
 142    $ git rebase FETCH_HEAD master
 143
 144Earlier, I said that rebase applies all the commits from your
 145branch on top of the upstream head.  Well, I lied.  "git rebase"
 146is a bit smarter than that and notices that #2 and #3 need not
 147be applied, so it only applies #1.  The commit ancestry graph
 148becomes something like this:
 149
 150   where                     *your old "master" head
 151  upstream --> #1 --> #2 --> #3
 152    used   \                      your new "master" head*
 153   to be     \--> #A --> #2' --> #3' --> #B --> #C --> #1'
 154                                                *upstream
 155                                                head
 156
 157Again, "git prune" would discard the disused commits #1-#3 and
 158you continue on starting from the new "master" head, which is
 159the #1' commit.
 160
 161-jc
 162
 163-
 164To unsubscribe from this list: send the line "unsubscribe git" in
 165the body of a message to majordomo@vger.kernel.org
 166More majordomo info at  http://vger.kernel.org/majordomo-info.html
 167
 168