Documentation: new upstream rebase recovery section in git-rebase
Document 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 <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Thomas Rast committed
Sep 13, 2008 at 18:11 UTC
90d1c08efcf9c688df207588d9b72178524a62b6
1 file changed
+125
-5
Documentation/git-rebase.txt
+125
-5
@@ -257,11 +257,10 @@ include::merge-strategies.txt[]
257
258
NOTES
259
-----
260
-When you rebase a branch, you are changing its history in a way that
261
-will cause problems for anyone who already has a copy of the branch
262
-in their repository and tries to pull updates from you. You should
263
-understand the implications of using 'git-rebase' on a repository that
264
-you share.
260
+
261
+You should understand the implications of using 'git-rebase' on a
262
+repository that you share. See also RECOVERING FROM UPSTREAM REBASE
263
+below.
264
265
When the git-rebase command is run, it will first execute a "pre-rebase"
266
hook if one exists. You can use this hook to do sanity checks and
@@ -396,6 +395,127 @@ consistent (they compile, pass the testsuite, etc.) you should use
395
after each commit, test, and amend the commit if fixes are necessary.
396
397
398
+RECOVERING FROM UPSTREAM REBASE
399
+-------------------------------
400
+
401
+Rebasing (or any other form of rewriting) a branch that others have
402
+based work on is a bad idea: anyone downstream of it is forced to
403
+manually fix their history. This section explains how to do the fix
404
+from the downstream's point of view. The real fix, however, would be
405
+to avoid rebasing the upstream in the first place.
406
+
407
+To illustrate, suppose you are in a situation where someone develops a
408
+'subsystem' branch, and you are working on a 'topic' that is dependent
409
+on this 'subsystem'. You might end up with a history like the
410
+following:
411
+
412
+------------
413
+ o---o---o---o---o---o---o---o---o master
414
+ \
415
+ o---o---o---o---o subsystem
416
+ \
417
+ *---*---* topic
418
+------------
419
+
420
+If 'subsystem' is rebased against 'master', the following happens:
421
+
422
+------------
423
+ o---o---o---o---o---o---o---o master
424
+ \ \
425
+ o---o---o---o---o o'--o'--o'--o'--o' subsystem
426
+ \
427
+ *---*---* topic
428
+------------
429
+
430
+If you now continue development as usual, and eventually merge 'topic'
431
+to 'subsystem', the commits from 'subsystem' will remain duplicated forever:
432
+
433
+------------
434
+ o---o---o---o---o---o---o---o master
435
+ \ \
436
+ o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
437
+ \ /
438
+ *---*---*-..........-*--* topic
439
+------------
440
+
441
+Such duplicates are generally frowned upon because they clutter up
442
+history, making it harder to follow. To clean things up, you need to
443
+transplant the commits on 'topic' to the new 'subsystem' tip, i.e.,
444
+rebase 'topic'. This becomes a ripple effect: anyone downstream from
445
+'topic' is forced to rebase too, and so on!
446
+
447
+There are two kinds of fixes, discussed in the following subsections:
448
+
449
+Easy case: The changes are literally the same.::
450
+
451
+ This happens if the 'subsystem' rebase was a simple rebase and
452
+ had no conflicts.
453
+
454
+Hard case: The changes are not the same.::
455
+
456
+ This happens if the 'subsystem' rebase had conflicts, or used
457
+ `\--interactive` to omit, edit, or squash commits; or if the
458
+ upstream used one of `commit \--amend`, `reset`, or
459
+ `filter-branch`.
460
+
461
+
462
+The easy case
463
+~~~~~~~~~~~~~
464
+
465
+Only works if the changes (patch IDs based on the diff contents) on
466
+'subsystem' are literally the same before and after the rebase
467
+'subsystem' did.
468
+
469
+In that case, the fix is easy because 'git-rebase' knows to skip
470
+changes that are already present in the new upstream. So if you say
471
+(assuming you're on 'topic')
472
+------------
473
+ $ git rebase subsystem
474
+------------
475
+you will end up with the fixed history
476
+------------
477
+ o---o---o---o---o---o---o---o master
478
+ \
479
+ o'--o'--o'--o'--o' subsystem
480
+ \
481
+ *---*---* topic
482
+------------
483
+
484
+
485
+The hard case
486
+~~~~~~~~~~~~~
487
+
488
+Things get more complicated if the 'subsystem' changes do not exactly
489
+correspond to the ones before the rebase.
490
+
491
+NOTE: While an "easy case recovery" sometimes appears to be successful
492
+ even in the hard case, it may have unintended consequences. For
493
+ example, a commit that was removed via `git rebase
494
+ \--interactive` will be **resurrected**!
495
+
496
+The idea is to manually tell 'git-rebase' "where the old 'subsystem'
497
+ended and your 'topic' began", that is, what the old merge-base
498
+between them was. You will have to find a way to name the last commit
499
+of the old 'subsystem', for example:
500
+
501
+* With the 'subsystem' reflog: after 'git-fetch', the old tip of
502
+ 'subsystem' is at `subsystem@\{1}`. Subsequent fetches will
503
+ increase the number. (See linkgit:git-reflog[1].)
504
+
505
+* Relative to the tip of 'topic': knowing that your 'topic' has three
506
+ commits, the old tip of 'subsystem' must be `topic~3`.
507
+
508
+You can then transplant the old `subsystem..topic` to the new tip by
509
+saying (for the reflog case, and assuming you are on 'topic' already):
510
+------------
511
+ $ git rebase --onto subsystem subsystem@{1}
512
+------------
513
+
514
+The ripple effect of a "hard case" recovery is especially bad:
515
+'everyone' downstream from 'topic' will now have to perform a "hard
516
+case" recovery too!
517
+
518
+
519
Authors
520
------
521
Written by Junio C Hamano <gitster@pobox.com> and