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 ... 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 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