Skip to content

Commit ad8261d

Browse files
johnkeepinggitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 48059e4 commit ad8261d

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

Documentation/git-rebase.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,16 @@ fresh commits so it can be remerged successfully without needing to "revert
324324
the reversion" (see the
325325
link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
326326

327+
--fork-point::
328+
--no-fork-point::
329+
Use 'git merge-base --fork-point' to find a better common ancestor
330+
between `upstream` and `branch` when calculating which commits have
331+
have been introduced by `branch` (see linkgit:git-merge-base[1]).
332+
+
333+
If no non-option arguments are given on the command line, then the default is
334+
`--fork-point @{u}` otherwise the `upstream` argument is interpreted literally
335+
unless the `--fork-point` option is specified.
336+
327337
--ignore-whitespace::
328338
--whitespace=<option>::
329339
These flag are passed to the 'git apply' program

git-rebase.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ git-rebase --continue | --abort | --skip | --edit-todo
1414
v,verbose! display a diffstat of what changed upstream
1515
q,quiet! be quiet. implies --no-stat
1616
autostash! automatically stash/stash pop before and after
17+
fork-point use 'merge-base --fork-point' to refine upstream
1718
onto=! rebase onto given branch instead of upstream
1819
p,preserve-merges! try to recreate merges instead of ignoring them
1920
s,strategy=! use the given merge strategy
@@ -66,6 +67,7 @@ verbose=
6667
diffstat=
6768
test "$(git config --bool rebase.stat)" = true && diffstat=t
6869
autostash="$(git config --bool rebase.autostash || echo false)"
70+
fork_point=auto
6971
git_am_opt=
7072
rebase_root=
7173
force_rebase=
@@ -260,6 +262,12 @@ do
260262
--no-autosquash)
261263
autosquash=
262264
;;
265+
--fork-point)
266+
fork_point=t
267+
;;
268+
--no-fork-point)
269+
fork_point=
270+
;;
263271
-M|-m)
264272
do_merge=t
265273
;;
@@ -437,6 +445,8 @@ then
437445
error_on_missing_default_upstream "rebase" "rebase" \
438446
"against" "git rebase <branch>"
439447
fi
448+
449+
test "$fork_point" = auto && fork_point=t
440450
;;
441451
*) upstream_name="$1"
442452
shift
@@ -522,6 +532,15 @@ case "$#" in
522532
;;
523533
esac
524534

535+
if test "$fork_point" = t
536+
then
537+
new_upstream=$(git merge-base --fork-point "$upstream_name" "$switch_to")
538+
if test -n "$new_upstream"
539+
then
540+
upstream=$new_upstream
541+
fi
542+
fi
543+
525544
if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
526545
then
527546
stash_sha1=$(git stash create "autostash") ||

t/t3400-rebase.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,14 @@ test_expect_success 'fail when upstream arg is missing and not configured' '
134134
test_must_fail git rebase
135135
'
136136

137-
test_expect_success 'default to @{upstream} when upstream arg is missing' '
137+
test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg' '
138138
git checkout -b default topic &&
139139
git config branch.default.remote . &&
140140
git config branch.default.merge refs/heads/master &&
141141
git rebase &&
142-
test "$(git rev-parse default~1)" = "$(git rev-parse master)"
142+
git rev-parse --verify master >expect &&
143+
git rev-parse default~1 >actual &&
144+
test_cmp expect actual
143145
'
144146

145147
test_expect_success 'rebase -q is quiet' '

0 commit comments

Comments
 (0)