rebase from internal branch

3

Click here to load reader

Upload: luzadorro

Post on 03-Apr-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Rebase From Internal Branch

7/28/2019 Rebase From Internal Branch

http://slidepdf.com/reader/full/rebase-from-internal-branch 1/3

From: Junio C Hamano <[email protected]>To: [email protected]: Petr Baudis <[email protected]>, Linus Torvalds <[email protected]>Subject: Re: sending changesets from the middle of a git treeDate: Sun, 14 Aug 2005 18:37:39 -0700Abstract: In this article, JC talks about how he rebases the

public "pu" branch using the core GIT tools when he updatesthe "master" branch, and how "rebase" works. Also discussedis how this applies to individual developers who sends patchesupstream.

Content-type: text/asciidoc

How to rebase from an internal branch=====================================

--------------------------------------Petr Baudis <[email protected]> writes:

> Dear diary, on Sun, Aug 14, 2005 at 09:57:13AM CEST, I got a letter> where Junio C Hamano <[email protected]> told me that...>> Linus Torvalds <[email protected]> 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 speakup. With its basing philosophical ancestry on quilt, this isthe kind of task StGIT is designed to do.

I just have done a simpler one, this time using only the coreGIT tools.

I had a handful of commits that were ahead of master in pu, and Iwanted to add some documentation bypassing my usual habit of

placing new things in pu first. At the beginning, the commitancestry graph looked like this:

*"pu" headmaster --> #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" headmaster^ --> #1 --> #2 --> #3

\\---> master

The old master is now master^ (the first parent of the master).The new master commit holds my documentation updates.

Page 2: Rebase From Internal Branch

7/28/2019 Rebase From Internal Branch

http://slidepdf.com/reader/full/rebase-from-internal-branch 2/3

Now I have to deal with "pu" branch.

This is the kind of situation I used to have all the time whenLinus was the maintainer and I was a contributor, when you lookat "master" branch being the "maintainer" branch, and "pu"branch being the "contributor" branch. Your work started at thetip of the "maintainer" branch some time ago, you made a lot ofprogress in the meantime, and now the maintainer branch has someother commits you do not have yet. And "git rebase" was writtenwith the explicit purpose of helping to maintain branches like"pu". You _could_ merge master to pu and keep going, but if youeventually want to cherrypick and merge some but not necessarilyall changes back to the master branch, it often makes lateroperations for _you_ easier if you rebase (i.e. carry forwardyour 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 currentbranch (note that I now am on "pu" branch) forked from themaster 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 andcommitted 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/ fileanymore, so after doing this you will have dangling commit ifyou ran fsck-cache, which is normal. After testing "pu", youcan run "git prune" to get rid of those original three commits.

While I am talking about "git rebase", I should talk about howto 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 andmade a couple of commits on top of it.

*your "master" headupstream --> #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. Sendthem out "To: " your project maintainer and "Cc: " your mailinglist. You could use contributed script git-send-email ifyour host has necessary perl modules for this, but your usualMUA would do as long as it does not corrupt whitespaces in thepatch.

Page 3: Rebase From Internal Branch

7/28/2019 Rebase From Internal Branch

http://slidepdf.com/reader/full/rebase-from-internal-branch 3/3

Then you would wait, and you find out that the upstream pickedup your changes, along with other changes.

where *your "master" headupstream --> #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 samechanges your e-mail submission for #2 and #3 contained, butprobably with the new sign-off line added by the upstreammaintainer and definitely with different committer and ancestryinformation, 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 butdoes not touch your .git/HEAD nor .git/refs/heads/master.You run "git rebase" now.

$ git rebase FETCH_HEAD masterEarlier, I said that rebase applies all the commits from yourbranch on top of the upstream head. Well, I lied. "git rebase"is a bit smarter than that and notices that #2 and #3 need notbe applied, so it only applies #1. The commit ancestry graphbecomes something like this:

where *your old "master" headupstream --> #1 --> #2 --> #3

used \ your new "master" head*to be \--> #A --> #2' --> #3' --> #B --> #C --> #1'

*upstream

headAgain, "git prune" would discard the disused commits #1-#3 andyou continue on starting from the new "master" head, which isthe #1' commit.

-jc