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