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