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