aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>2008-01-26 18:04:37 +0000
committerJunio C Hamano <gitster@pobox.com>2008-01-26 18:24:24 -0800
commitc85c79279df2c8a583d95449d1029baba41f8660 (patch)
tree41a2936893206ec54c80bb6e9004f760fdaf303f
parente509db990b2ecae642efe3cdef4014d57d525f24 (diff)
downloadgit-c85c79279df2c8a583d95449d1029baba41f8660.tar.gz
git-c85c79279df2c8a583d95449d1029baba41f8660.tar.xz
pull --rebase: be cleverer with rebased upstream branches
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>
-rw-r--r--Documentation/git-pull.txt6
-rwxr-xr-xgit-pull.sh12
-rwxr-xr-xt/t5520-pull.sh17
3 files changed, 33 insertions, 2 deletions
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index f9f1e0d30..4cc633a5e 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -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
diff --git a/git-pull.sh b/git-pull.sh
index fa97b0f35..46da0f4ca 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -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
@@ -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
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 52b3a0c6d..9484129ca 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -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