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