Some instances replaced by "handful of", others use the word "few", a couple get a slight rewording. Signed-off-by: Jon Loeliger <jdl@freescale.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
		
			
				
	
	
		
			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
 |