Browse files

rebase: use reflog to find common base with upstream

Commit 15a147e (rebase: use @{upstream} if no upstream specified,
2011-02-09) says:

	Make it default to 'git rebase @{upstream}'. That is also what
	'git pull [--rebase]' defaults to, so it only makes sense that
	'git rebase' defaults to the same thing.

but that isn't actually the case.  Since commit d44e712 (pull: support
rebased upstream + fetch + pull --rebase, 2009-07-19), pull has actually
chosen the most recent reflog entry which is an ancestor of the current
branch if it can find one.

Add a '--fork-point' argument to git-rebase that can be used to trigger
this behaviour.  This option is turned on by default if no non-option
arguments are specified on the command line, otherwise we treat an
upstream specified on the command-line literally.

Signed-off-by: John Keeping <>
Signed-off-by: Junio C Hamano <>
  • Loading branch information...
1 parent 48059e4 commit ad8261d21221d27638c75f47b39892db6f7972f6 @johnkeeping johnkeeping committed with gitster Dec 9, 2013
Showing with 33 additions and 2 deletions.
  1. +10 −0 Documentation/git-rebase.txt
  2. +19 −0
  3. +4 −2 t/
10 Documentation/git-rebase.txt
@@ -324,6 +324,16 @@ fresh commits so it can be remerged successfully without needing to "revert
the reversion" (see the
link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
+ Use 'git merge-base --fork-point' to find a better common ancestor
+ between `upstream` and `branch` when calculating which commits have
+ have been introduced by `branch` (see linkgit:git-merge-base[1]).
+If no non-option arguments are given on the command line, then the default is
+`--fork-point @{u}` otherwise the `upstream` argument is interpreted literally
+unless the `--fork-point` option is specified.
These flag are passed to the 'git apply' program
@@ -14,6 +14,7 @@ git-rebase --continue | --abort | --skip | --edit-todo
v,verbose! display a diffstat of what changed upstream
q,quiet! be quiet. implies --no-stat
autostash! automatically stash/stash pop before and after
+fork-point use 'merge-base --fork-point' to refine upstream
onto=! rebase onto given branch instead of upstream
p,preserve-merges! try to recreate merges instead of ignoring them
s,strategy=! use the given merge strategy
@@ -66,6 +67,7 @@ verbose=
test "$(git config --bool rebase.stat)" = true && diffstat=t
autostash="$(git config --bool rebase.autostash || echo false)"
@@ -260,6 +262,12 @@ do
+ --fork-point)
+ fork_point=t
+ ;;
+ --no-fork-point)
+ fork_point=
+ ;;
@@ -437,6 +445,8 @@ then
error_on_missing_default_upstream "rebase" "rebase" \
"against" "git rebase <branch>"
+ test "$fork_point" = auto && fork_point=t
*) upstream_name="$1"
@@ -522,6 +532,15 @@ case "$#" in
+if test "$fork_point" = t
+ new_upstream=$(git merge-base --fork-point "$upstream_name" "$switch_to")
+ if test -n "$new_upstream"
+ then
+ upstream=$new_upstream
+ fi
if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
stash_sha1=$(git stash create "autostash") ||
6 t/
@@ -134,12 +134,14 @@ test_expect_success 'fail when upstream arg is missing and not configured' '
test_must_fail git rebase
-test_expect_success 'default to @{upstream} when upstream arg is missing' '
+test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg' '
git checkout -b default topic &&
git config branch.default.remote . &&
git config branch.default.merge refs/heads/master &&
git rebase &&
- test "$(git rev-parse default~1)" = "$(git rev-parse master)"
+ git rev-parse --verify master >expect &&
+ git rev-parse default~1 >actual &&
+ test_cmp expect actual
test_expect_success 'rebase -q is quiet' '

0 comments on commit ad8261d

Please sign in to comment.