blob: f2e10a7ec88664be4c31db7ae9770281db343a74 [file] [log] [blame]
Junio C Hamano59eb68a2008-07-21 12:14:42 -07001From: Junio C Hamano <gitster@pobox.com>
Ryan Anderson365a00a2005-08-15 04:25:53 -04002To: 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
Junio C Hamanof358c102005-08-26 12:35:51 -07006Abstract: In this article, JC talks about how he rebases the
Johannes Schindelin77dc6042020-06-25 12:18:58 +00007 public "seen" branch using the core Git tools when he updates
Junio C Hamanof358c102005-08-26 12:35:51 -07008 the "master" branch, and how "rebase" works. Also discussed
9 is how this applies to individual developers who sends patches
10 upstream.
Thomas Ackermann1797e5c2012-10-16 19:25:29 +020011Content-type: text/asciidoc
Ryan Anderson365a00a2005-08-15 04:25:53 -040012
Thomas Ackermann1797e5c2012-10-16 19:25:29 +020013How to rebase from an internal branch
14=====================================
15
16--------------------------------------
Ryan Anderson365a00a2005-08-15 04:25:53 -040017Petr 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:
Junio C Hamanoa6080a02007-06-07 00:04:01 -070022>>
Johannes Schindelin77dc6042020-06-25 12:18:58 +000023>> > Junio, maybe you want to talk about how you move patches from your
24>> > "seen" branch to the real branches.
Junio C Hamanoa6080a02007-06-07 00:04:01 -070025>>
Ryan Anderson365a00a2005-08-15 04:25:53 -040026> Actually, wouldn't this be also precisely for what StGIT is intended to?
Thomas Ackermann1797e5c2012-10-16 19:25:29 +020027--------------------------------------
Ryan Anderson365a00a2005-08-15 04:25:53 -040028
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
Thomas Ackermann48a8c262013-01-21 20:16:20 +010034Git tools.
Ryan Anderson365a00a2005-08-15 04:25:53 -040035
Johannes Schindelin77dc6042020-06-25 12:18:58 +000036I had a handful of commits that were ahead of master in 'seen', and I
Ryan Anderson365a00a2005-08-15 04:25:53 -040037wanted to add some documentation bypassing my usual habit of
Johannes Schindelin77dc6042020-06-25 12:18:58 +000038placing new things in 'seen' first. At the beginning, the commit
Ryan Anderson365a00a2005-08-15 04:25:53 -040039ancestry graph looked like this:
40
Johannes Schindelin77dc6042020-06-25 12:18:58 +000041 *"seen" head
Ryan Anderson365a00a2005-08-15 04:25:53 -040042 master --> #1 --> #2 --> #3
43
44So I started from master, made a bunch of edits, and committed:
45
46 $ git checkout master
Junio C Hamanoe47e35a2005-08-26 17:27:07 -070047 $ cd Documentation; ed git.txt ...
Ryan Anderson365a00a2005-08-15 04:25:53 -040048 $ cd ..; git add Documentation/*.txt
Junio C Hamano22a06b32005-11-19 19:21:11 -080049 $ git commit -s
Ryan Anderson365a00a2005-08-15 04:25:53 -040050
51After the commit, the ancestry graph would look like this:
52
Johannes Schindelin77dc6042020-06-25 12:18:58 +000053 *"seen" head
Ryan Anderson365a00a2005-08-15 04:25:53 -040054 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
Johannes Schindelin77dc6042020-06-25 12:18:58 +000061Now I have to deal with "seen" branch.
Ryan Anderson365a00a2005-08-15 04:25:53 -040062
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
Johannes Schindelin77dc6042020-06-25 12:18:58 +000065at "master" branch being the "maintainer" branch, and "seen"
Ryan Anderson365a00a2005-08-15 04:25:53 -040066branch 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
Johannes Schindelin77dc6042020-06-25 12:18:58 +000071"seen". You _could_ merge master to 'seen' and keep going, but if you
Ryan Anderson365a00a2005-08-15 04:25:53 -040072eventually 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
Johannes Schindelin77dc6042020-06-25 12:18:58 +000075your changes) "seen" rather than merge. So I ran "git rebase":
Ryan Anderson365a00a2005-08-15 04:25:53 -040076
Johannes Schindelin77dc6042020-06-25 12:18:58 +000077 $ git checkout seen
78 $ git rebase master seen
Ryan Anderson365a00a2005-08-15 04:25:53 -040079
80What this does is to pick all the commits since the current
Johannes Schindelin77dc6042020-06-25 12:18:58 +000081branch (note that I now am on "seen" branch) forked from the
Ryan Anderson365a00a2005-08-15 04:25:53 -040082master branch, and forward port these changes.
83
84 master^ --> #1 --> #2 --> #3
Johannes Schindelin77dc6042020-06-25 12:18:58 +000085 \ *"seen" head
Ryan Anderson365a00a2005-08-15 04:25:53 -040086 \---> 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
Johannes Schindelin77dc6042020-06-25 12:18:58 +000095you ran fsck-cache, which is normal. After testing "seen", you
Ryan Anderson365a00a2005-08-15 04:25:53 -040096can run "git prune" to get rid of those original three commits.
97
98While I am talking about "git rebase", I should talk about how
Thomas Ackermann48a8c262013-01-21 20:16:20 +010099to do cherrypicking using only the core Git tools.
Ryan Anderson365a00a2005-08-15 04:25:53 -0400100
101Let's go back to the earlier picture, with different labels.
102
103You, as an individual developer, cloned upstream repository and
Junio C Hamano22a06b32005-11-19 19:21:11 -0800104made a couple of commits on top of it.
Ryan Anderson365a00a2005-08-15 04:25:53 -0400105
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
Junio C Hamano917a8f82007-01-17 15:03:39 -0800115This creates two files, 0001-XXXX.patch and 0002-XXXX.patch. Send
Ryan Anderson365a00a2005-08-15 04:25:53 -0400116them out "To: " your project maintainer and "Cc: " your mailing
Junio C Hamano215a7ad2005-09-07 17:26:23 -0700117list. You could use contributed script git-send-email if
Ryan Anderson365a00a2005-08-15 04:25:53 -0400118your 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
Junio C Hamanoa6080a02007-06-07 00:04:01 -0700127 used \
Ryan Anderson365a00a2005-08-15 04:25:53 -0400128 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
Pavel Roskinaddf88e2006-07-09 03:44:30 -0400133probably with the new sign-off line added by the upstream
Ryan Anderson365a00a2005-08-15 04:25:53 -0400134maintainer 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
Justin Lebara58088a2014-03-31 15:11:44 -0700142does not touch your .git/HEAD or .git/refs/heads/master.
Ryan Anderson365a00a2005-08-15 04:25:53 -0400143You 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