path: root/Documentation/howto/rebase-from-internal-branch.txt
diff options
authorRyan Anderson <>2005-08-15 08:25:53 (GMT)
committerJunio C Hamano <>2005-08-15 10:00:21 (GMT)
commit365a00a3f280f8697e4735e1ac5b42a1c50f7887 (patch)
tree3ce890c43c4f6323a4c393383b1b8c093c0654e5 /Documentation/howto/rebase-from-internal-branch.txt
parentc65a9470fbaa57b9b815addde51ad22648f6d353 (diff)
[PATCH] Add some simple howtos, culled from the mailing list.
I think these are useful, and I think putting them in a new "howto" directory might help some users until we get to the point of splitting up the tutorial to be easier to read. Given the authorship, I think it's safe to put these in the repository. Signed-off-by: Ryan Anderson <>
Diffstat (limited to 'Documentation/howto/rebase-from-internal-branch.txt')
1 files changed, 163 insertions, 0 deletions
diff --git a/Documentation/howto/rebase-from-internal-branch.txt b/Documentation/howto/rebase-from-internal-branch.txt
new file mode 100644
index 0000000..8109b7f
--- /dev/null
+++ b/Documentation/howto/rebase-from-internal-branch.txt
@@ -0,0 +1,163 @@
+From: Junio C Hamano <>
+Cc: Petr Baudis <>, Linus Torvalds <>
+Subject: Re: sending changesets from the middle of a git tree
+Date: Sun, 14 Aug 2005 18:37:39 -0700
+Petr Baudis <> writes:
+> Dear diary, on Sun, Aug 14, 2005 at 09:57:13AM CEST, I got a letter
+> where Junio C Hamano <> told me that...
+>> Linus Torvalds <> 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 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 git-apply-patch-script.txt ...
+ $ cd ..; git add Documentation/*.txt
+ $ git commit -s -v
+NOTE. The -v flag to commit is a handy way to make sure that
+your additions are not introducing bogusly formatted lines.
+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
+amde 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.txt and 0002-XXXX.txt. Send
+them out "To: " your project maintainer and "Cc: " your mailing
+list. You could use contributed script git-send-email-script 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
+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 upsteam
+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.
+To unsubscribe from this list: send the line "unsubscribe git" in
+the body of a message to
+More majordomo info at