Thread (16 messages) flat view 16 messages, 6 authors, 2016-06-15
STALE3707d

[PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase

From: Thomas Rast <hidden>
Date: 2016-06-15 22:45:21
Subsystem: documentation, the rest · Maintainers: Jonathan Corbet, Linus Torvalds

Possibly related (same subject, not in this thread)

Documents how to recover if the upstream that you pull from has
rebased the branches you depend your work on.  Hopefully this can also
serve as a warning to potential rebasers.

Signed-off-by: Thomas Rast <redacted>
---
 Documentation/git-rebase.txt |  103 +++++++++++++++++++++++++++++++++++++++--
 1 files changed, 98 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 59c1b02..ba5255d 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -257,11 +257,10 @@ include::merge-strategies.txt[]
 
 NOTES
 -----
-When you rebase a branch, you are changing its history in a way that
-will cause problems for anyone who already has a copy of the branch
-in their repository and tries to pull updates from you.  You should
-understand the implications of using 'git-rebase' on a repository that
-you share.
+
+You should understand the implications of using 'git-rebase' on a
+repository that you share.  See also RECOVERING FROM UPSTREAM REBASE
+below.
 
 When the git-rebase command is run, it will first execute a "pre-rebase"
 hook if one exists.  You can use this hook to do sanity checks and
@@ -396,6 +395,100 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+RECOVERING FROM UPSTREAM REBASE
+-------------------------------
+
+This section briefly explains the problems that arise from rebasing or
+rewriting published branches, and shows how to recover.  As you will
+see, the process is rather tedious, so we emphasize again: 'Avoid
+rewriting published history.'  This goes for `rebase`, `commit
+--amend`, `reset HEAD^` and `filter-branch` alike.
+
+To illustrate, suppose you are in a situation where someone develops a
+'subsystem' branch, and you are working on a 'topic' that is dependent
+on this 'subsystem'.  You might end up with a history like the
+following:
+
+------------
+    o---o---o---o---o  master
+	 \
+	  o---o---o---o---o  subsystem
+			   \
+			    *---*---*  topic
+------------
+
+If 'subsystem' is rebased against master, the following happens:
+
+------------
+    o---o---o---o---o  master
+	|	     \
+	|	      o'--o'--o'--o'--o'  subsystem
+	\
+	 o---o---o---o---o---*---*---*	topic
+------------
+
+Note that while we have marked your own commits with a '*', there is
+nothing that distinguishes them from the commits that previously were
+on 'subsystem'.  Luckily, 'git-rebase' knows to skip commits that are
+textually the same as commits in the upstream.  So if you say
+(assuming you're on 'topic')
+------------
+    git rebase subsystem
+------------
+you will end up with the fixed history
+------------
+    o---o---o---o---o  master
+		     \
+		      o'--o'--o'--o'--o'  subsystem
+					\
+					 *'--*'--*'  topic
+------------
+
+This becomes a ripple effect to anyone downstream of the first rebase:
+anyone downstream from 'topic' now needs to rebase too, and so on.
+
+Things get more complicated if your upstream used `git rebase
+--interactive` (or `commit --amend` or `reset --hard HEAD^`).  Label
+the example history as follows:
+
+------------
+    o---o---o---o---o  master
+	 \
+	  A---B---C---D---E  subsystem
+			   \
+			    X---Y---Z  topic
+------------
+
+Now suppose the 'subsystem' maintainer decides to clean up his history
+with an interactive rebase.  He edits commits A and D (marked with a
+`*`), decides to remove D entirely and moves B to the front.  This
+results in
+
+------------
+    o---o---o---o---o  master
+	|	     \
+	|	      A*--C*--E'--B'  subsystem
+	\
+	 A---B---C---D---E---X---Y---Z	topic
+------------
+
+'git-rebase' can still tell that E'=E and B'=B, so a plain `git rebase
+subsystem` would not duplicate those commits.  However, it would
+**resurrect** D (which may succeed silently!) and try to apply the
+original versions of A and C (probably resulting in conflicts).
+
+To fix this, you have to manually transplant your own part of the
+history to the new branch head.  Looking at `git log`, you should be
+able to determine that three commits on 'topic' are yours.  Again
+assuming you are already on 'topic', you can do
+------------
+    git rebase --onto subsystem HEAD~3
+------------
+to put things right.  Of course, this again ripples onwards:
+'everyone' downstream from 'subsystem' will have to 'manually' rebase
+all their work!
+
+
 Authors
 ------
 Written by Junio C Hamano <gitster@pobox.com> and
-- 
1.6.0.1.470.g200b
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help