164 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
| From:	Junio C Hamano <gitster@pobox.com>
 | |
| To:	git@vger.kernel.org
 | |
| Cc:	Petr Baudis <pasky@suse.cz>, Linus Torvalds <torvalds@osdl.org>
 | |
| Subject: Re: sending changesets from the middle of a git tree
 | |
| Date:	Sun, 14 Aug 2005 18:37:39 -0700
 | |
| Abstract: In this article, JC talks about how he rebases the
 | |
|  public "pu" branch using the core GIT tools when he updates
 | |
|  the "master" branch, and how "rebase" works.  Also discussed
 | |
|  is how this applies to individual developers who sends patches
 | |
|  upstream.
 | |
| 
 | |
| Petr Baudis <pasky@suse.cz> writes:
 | |
| 
 | |
| > Dear diary, on Sun, Aug 14, 2005 at 09:57:13AM CEST, I got a letter
 | |
| > where Junio C Hamano <junkio@cox.net> told me that...
 | |
| >> Linus Torvalds <torvalds@osdl.org> writes:
 | |
| >>
 | |
| >> > Junio, maybe you want to talk about how you move patches from your "pu"
 | |
| >> > branch to the real branches.
 | |
| >>
 | |
| > Actually, wouldn't this be also precisely for what StGIT is intended to?
 | |
| 
 | |
| Exactly my feeling.  I was sort of waiting for Catalin to speak
 | |
| up.  With its basing philosophical ancestry on quilt, this is
 | |
| the kind of task StGIT is designed to do.
 | |
| 
 | |
| I just have done a simpler one, this time using only the core
 | |
| GIT tools.
 | |
| 
 | |
| I had a handful of commits that were ahead of master in pu, and I
 | |
| wanted to add some documentation bypassing my usual habit of
 | |
| placing new things in pu first.  At the beginning, the commit
 | |
| ancestry graph looked like this:
 | |
| 
 | |
|                              *"pu" head
 | |
|     master --> #1 --> #2 --> #3
 | |
| 
 | |
| So I started from master, made a bunch of edits, and committed:
 | |
| 
 | |
|     $ git checkout master
 | |
|     $ cd Documentation; ed git.txt ...
 | |
|     $ cd ..; git add Documentation/*.txt
 | |
|     $ git commit -s
 | |
| 
 | |
| After the commit, the ancestry graph would look like this:
 | |
| 
 | |
|                               *"pu" head
 | |
|     master^ --> #1 --> #2 --> #3
 | |
|           \
 | |
|             \---> master
 | |
| 
 | |
| The old master is now master^ (the first parent of the master).
 | |
| The new master commit holds my documentation updates.
 | |
| 
 | |
| Now I have to deal with "pu" branch.
 | |
| 
 | |
| This is the kind of situation I used to have all the time when
 | |
| Linus was the maintainer and I was a contributor, when you look
 | |
| at "master" branch being the "maintainer" branch, and "pu"
 | |
| branch being the "contributor" branch.  Your work started at the
 | |
| tip of the "maintainer" branch some time ago, you made a lot of
 | |
| progress in the meantime, and now the maintainer branch has some
 | |
| other commits you do not have yet.  And "git rebase" was written
 | |
| with the explicit purpose of helping to maintain branches like
 | |
| "pu".  You _could_ merge master to pu and keep going, but if you
 | |
| eventually want to cherrypick and merge some but not necessarily
 | |
| all changes back to the master branch, it often makes later
 | |
| operations for _you_ easier if you rebase (i.e. carry forward
 | |
| your changes) "pu" rather than merge.  So I ran "git rebase":
 | |
| 
 | |
|     $ git checkout pu
 | |
|     $ git rebase master pu
 | |
| 
 | |
| What this does is to pick all the commits since the current
 | |
| branch (note that I now am on "pu" branch) forked from the
 | |
| master branch, and forward port these changes.
 | |
| 
 | |
|     master^ --> #1 --> #2 --> #3
 | |
|           \                                  *"pu" head
 | |
|             \---> master --> #1' --> #2' --> #3'
 | |
| 
 | |
| The diff between master^ and #1 is applied to master and
 | |
| committed to create #1' commit with the commit information (log,
 | |
| author and date) taken from commit #1.  On top of that #2' and #3'
 | |
| commits are made similarly out of #2 and #3 commits.
 | |
| 
 | |
| Old #3 is not recorded in any of the .git/refs/heads/ file
 | |
| anymore, so after doing this you will have dangling commit if
 | |
| you ran fsck-cache, which is normal.  After testing "pu", you
 | |
| can run "git prune" to get rid of those original three commits.
 | |
| 
 | |
| While I am talking about "git rebase", I should talk about how
 | |
| to do cherrypicking using only the core GIT tools.
 | |
| 
 | |
| Let's go back to the earlier picture, with different labels.
 | |
| 
 | |
| You, as an individual developer, cloned upstream repository and
 | |
| made a couple of commits on top of it.
 | |
| 
 | |
|                               *your "master" head
 | |
|    upstream --> #1 --> #2 --> #3
 | |
| 
 | |
| You would want changes #2 and #3 incorporated in the upstream,
 | |
| while you feel that #1 may need further improvements.  So you
 | |
| prepare #2 and #3 for e-mail submission.
 | |
| 
 | |
|     $ git format-patch master^^ master
 | |
| 
 | |
| This creates two files, 0001-XXXX.patch and 0002-XXXX.patch.  Send
 | |
| them out "To: " your project maintainer and "Cc: " your mailing
 | |
| list.  You could use contributed script git-send-email if
 | |
| your host has necessary perl modules for this, but your usual
 | |
| MUA would do as long as it does not corrupt whitespaces in the
 | |
| patch.
 | |
| 
 | |
| Then you would wait, and you find out that the upstream picked
 | |
| up your changes, along with other changes.
 | |
| 
 | |
|    where                      *your "master" head
 | |
|   upstream --> #1 --> #2 --> #3
 | |
|     used   \
 | |
|    to be     \--> #A --> #2' --> #3' --> #B --> #C
 | |
|                                                 *upstream head
 | |
| 
 | |
| The two commits #2' and #3' in the above picture record the same
 | |
| changes your e-mail submission for #2 and #3 contained, but
 | |
| probably with the new sign-off line added by the upstream
 | |
| maintainer and definitely with different committer and ancestry
 | |
| information, they are different objects from #2 and #3 commits.
 | |
| 
 | |
| You fetch from upstream, but not merge.
 | |
| 
 | |
|     $ git fetch upstream
 | |
| 
 | |
| This leaves the updated upstream head in .git/FETCH_HEAD but
 | |
| does not touch your .git/HEAD nor .git/refs/heads/master.
 | |
| You run "git rebase" now.
 | |
| 
 | |
|     $ git rebase FETCH_HEAD master
 | |
| 
 | |
| Earlier, I said that rebase applies all the commits from your
 | |
| branch on top of the upstream head.  Well, I lied.  "git rebase"
 | |
| is a bit smarter than that and notices that #2 and #3 need not
 | |
| be applied, so it only applies #1.  The commit ancestry graph
 | |
| becomes something like this:
 | |
| 
 | |
|    where                     *your old "master" head
 | |
|   upstream --> #1 --> #2 --> #3
 | |
|     used   \                      your new "master" head*
 | |
|    to be     \--> #A --> #2' --> #3' --> #B --> #C --> #1'
 | |
|                                                 *upstream
 | |
|                                                 head
 | |
| 
 | |
| Again, "git prune" would discard the disused commits #1-#3 and
 | |
| you continue on starting from the new "master" head, which is
 | |
| the #1' commit.
 | |
| 
 | |
| -jc
 | |
| 
 | |
| -
 | |
| To unsubscribe from this list: send the line "unsubscribe git" in
 | |
| the body of a message to majordomo@vger.kernel.org
 | |
| More majordomo info at  http://vger.kernel.org/majordomo-info.html
 |