Skip to content

Commit

Permalink
pull --rebase: be cleverer with rebased upstream branches
Browse files Browse the repository at this point in the history
When the upstream branch is tracked, we can detect if that branch
was rebased since it was last fetched.  Teach git to use that
information to rebase from the old remote head onto the new remote head.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Johannes Schindelin authored and Junio C Hamano committed Jan 27, 2008
1 parent e509db9 commit c85c792
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
6 changes: 5 additions & 1 deletion Documentation/git-pull.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ include::urls-remotes.txt[]
include::merge-strategies.txt[]

\--rebase::
Instead of a merge, perform a rebase after fetching.
Instead of a merge, perform a rebase after fetching. If
there is a remote ref for the upstream branch, and this branch
was rebased since last fetched, the rebase uses that information
to avoid rebasing non-local changes.

*NOTE:* This is a potentially _dangerous_ mode of operation.
It rewrites history, which does not bode well when you
published that history already. Do *not* use this option
Expand Down
12 changes: 11 additions & 1 deletion git-pull.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ error_on_no_merge_candidates () {
exit 1
}

test true = "$rebase" && {
. git-parse-remote &&
origin="$1"
test -z "$origin" && origin=$(get_default_remote)
reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
sed "s|refs/heads/\(.*\):|\1|")" &&
oldremoteref="$(git rev-parse --verify \
"refs/remotes/$origin/$reflist" 2>/dev/null)"
}
orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
git-fetch --update-head-ok "$@" || exit 1

Expand Down Expand Up @@ -164,6 +173,7 @@ then
fi

merge_name=$(git fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit
test true = "$rebase" && exec git-rebase $merge_head
test true = "$rebase" &&
exec git-rebase --onto $merge_head ${oldremoteref:-$merge_head}
exec git-merge $no_summary $no_commit $squash $no_ff $strategy_args \
"$merge_name" HEAD $merge_head
17 changes: 17 additions & 0 deletions t/t5520-pull.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,25 @@ test_expect_success 'branch.to-rebase.rebase' '
git reset --hard before-rebase &&
git config branch.to-rebase.rebase 1 &&
git pull . copy &&
git config branch.to-rebase.rebase 0 &&
test $(git rev-parse HEAD^) = $(git rev-parse copy) &&
test new = $(git show HEAD:file2)
'

test_expect_success '--rebase with rebased upstream' '
git remote add -f me . &&
git checkout copy &&
git reset --hard HEAD^ &&
echo conflicting modification > file &&
git commit -m conflict file &&
git checkout to-rebase &&
echo file > file2 &&
git commit -m to-rebase file2 &&
git pull --rebase me copy &&
test "conflicting modification" = "$(cat file)" &&
test file = $(cat file2)
'

test_done

0 comments on commit c85c792

Please sign in to comment.