]>
Commit | Line | Data |
---|---|---|
59eb68aa | 1 | From: Junio C Hamano <gitster@pobox.com> |
365a00a3 RA |
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 | |
f358c10f | 6 | Abstract: In this article, JC talks about how he rebases the |
77dc6049 | 7 | public "seen" branch using the core Git tools when he updates |
f358c10f JH |
8 | the "master" branch, and how "rebase" works. Also discussed |
9 | is how this applies to individual developers who sends patches | |
10 | upstream. | |
1797e5c5 | 11 | Content-type: text/asciidoc |
365a00a3 | 12 | |
1797e5c5 TA |
13 | How to rebase from an internal branch |
14 | ===================================== | |
15 | ||
16 | -------------------------------------- | |
365a00a3 RA |
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: | |
a6080a0a | 22 | >> |
77dc6049 JS |
23 | >> > Junio, maybe you want to talk about how you move patches from your |
24 | >> > "seen" branch to the real branches. | |
a6080a0a | 25 | >> |
365a00a3 | 26 | > Actually, wouldn't this be also precisely for what StGIT is intended to? |
1797e5c5 | 27 | -------------------------------------- |
365a00a3 RA |
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 | |
48a8c26c | 34 | Git tools. |
365a00a3 | 35 | |
77dc6049 | 36 | I had a handful of commits that were ahead of master in 'seen', and I |
365a00a3 | 37 | wanted to add some documentation bypassing my usual habit of |
77dc6049 | 38 | placing new things in 'seen' first. At the beginning, the commit |
365a00a3 RA |
39 | ancestry graph looked like this: |
40 | ||
77dc6049 | 41 | *"seen" head |
365a00a3 RA |
42 | master --> #1 --> #2 --> #3 |
43 | ||
44 | So I started from master, made a bunch of edits, and committed: | |
45 | ||
46 | $ git checkout master | |
e47e35ac | 47 | $ cd Documentation; ed git.txt ... |
365a00a3 | 48 | $ cd ..; git add Documentation/*.txt |
22a06b3c | 49 | $ git commit -s |
365a00a3 RA |
50 | |
51 | After the commit, the ancestry graph would look like this: | |
52 | ||
77dc6049 | 53 | *"seen" head |
365a00a3 RA |
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 | ||
77dc6049 | 61 | Now I have to deal with "seen" branch. |
365a00a3 RA |
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 | |
77dc6049 | 65 | at "master" branch being the "maintainer" branch, and "seen" |
365a00a3 RA |
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 | |
77dc6049 | 71 | "seen". You _could_ merge master to 'seen' and keep going, but if you |
365a00a3 RA |
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 | |
77dc6049 | 75 | your changes) "seen" rather than merge. So I ran "git rebase": |
365a00a3 | 76 | |
77dc6049 JS |
77 | $ git checkout seen |
78 | $ git rebase master seen | |
365a00a3 RA |
79 | |
80 | What this does is to pick all the commits since the current | |
77dc6049 | 81 | branch (note that I now am on "seen" branch) forked from the |
365a00a3 RA |
82 | master branch, and forward port these changes. |
83 | ||
84 | master^ --> #1 --> #2 --> #3 | |
77dc6049 | 85 | \ *"seen" head |
365a00a3 RA |
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 | |
77dc6049 | 95 | you ran fsck-cache, which is normal. After testing "seen", you |
365a00a3 RA |
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 | |
48a8c26c | 99 | to do cherrypicking using only the core Git tools. |
365a00a3 RA |
100 | |
101 | Let's go back to the earlier picture, with different labels. | |
102 | ||
103 | You, as an individual developer, cloned upstream repository and | |
22a06b3c | 104 | made a couple of commits on top of it. |
365a00a3 RA |
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 | ||
917a8f89 | 115 | This creates two files, 0001-XXXX.patch and 0002-XXXX.patch. Send |
365a00a3 | 116 | them out "To: " your project maintainer and "Cc: " your mailing |
215a7ad1 | 117 | list. You could use contributed script git-send-email if |
365a00a3 RA |
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 | |
a6080a0a | 127 | used \ |
365a00a3 RA |
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 | |
addf88e4 | 133 | probably with the new sign-off line added by the upstream |
365a00a3 RA |
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 | |
a58088ab | 142 | does not touch your .git/HEAD or .git/refs/heads/master. |
365a00a3 RA |
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 |