git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/2] Fix spurious conflicts with pull --rebase
@ 2010-08-06 14:05 Elijah Newren
  2010-08-06 14:05 ` [PATCH 1/2] t5520-pull: Add testcases showing spurious conflicts from git " Elijah Newren
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Elijah Newren @ 2010-08-06 14:05 UTC (permalink / raw
  To: git; +Cc: Santi Béjar, gitster, Elijah Newren

This patch series fixes git pull --rebase failing to detect if "local"
patches are already upstream in cases where the upstream repository is
not itself rebased.  Also in the non-rebased upstream case, this
series avoids checking/applying more patches than needed (i.e. avoids
having rebase work on commits which are already reachable from
upstream).

It would be nice to make 'git pull --rebase' able to detect if patches
being applied are already part of upstream in cases where the upstream
repository has been rebased.  As far as I can tell, that would require
changes to format-patch to allow it to be told what 'upstream' is, and
some changes to git-pull.sh/git-rebase.sh to pass it this information.

Elijah Newren (2):
  t5520-pull: Add testcases showing spurious conflicts from git pull
    --rebase
  pull --rebase: Avoid spurious conflicts and reapplying unnecessary
    patches

 git-pull.sh     |   34 ++++++++++++++++++++-----------
 t/t5520-pull.sh |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 12 deletions(-)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] t5520-pull: Add testcases showing spurious conflicts from git pull --rebase
  2010-08-06 14:05 [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren
@ 2010-08-06 14:05 ` Elijah Newren
  2010-08-06 14:05 ` [PATCH 2/2] pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches Elijah Newren
  2010-08-08 19:27 ` [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren
  2 siblings, 0 replies; 4+ messages in thread
From: Elijah Newren @ 2010-08-06 14:05 UTC (permalink / raw
  To: git; +Cc: Santi Béjar, gitster, Elijah Newren


Signed-off-by: Elijah Newren <newren@gmail.com>
---
 t/t5520-pull.sh |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 319e389..8f76829 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -160,4 +160,63 @@ test_expect_success 'pull --rebase works on branch yet to be born' '
 	test_cmp expect actual
 '
 
+test_expect_success 'setup for detecting upstreamed changes' '
+	mkdir src &&
+	(cd src &&
+	 git init &&
+	 for i in $(seq 1 10); do echo $i; done > stuff &&
+	 git add stuff &&
+	 git commit -m "Initial revision"
+	) &&
+	git clone src dst &&
+	(cd src &&
+	 sed -i s/5/43/ stuff &&
+	 git commit -a -m "5->43" &&
+	 sed -i s/6/42/ stuff &&
+	 git commit -a -m "Make it bigger" &&
+	 correct=$(git rev-parse HEAD)
+	) &&
+	(cd dst &&
+	 sed -i s/5/43/ stuff &&
+	 git commit -a -m "Independent discovery of 5->43"
+	)
+'
+
+test_expect_failure 'git pull --rebase detects upstreamed changes' '
+	(cd dst &&
+	 git pull --rebase &&
+	 test -z "$(git ls-files -u)"
+	)
+'
+
+test_expect_success 'setup for avoiding reapplying old patches' '
+	(cd dst &&
+	 (git rebase --abort || true) &&
+	 git reset --hard origin/master
+	) &&
+	git clone --bare src src-replace.git &&
+	rm -rf src &&
+	mv src-replace.git src &&
+	(cd dst &&
+	 sed -i s/2/22/ stuff &&
+	 git commit -a -m "Change 2" &&
+	 sed -i s/3/33/ stuff &&
+	 git commit -a -m "Change 3" &&
+	 sed -i s/4/44/ stuff &&
+	 git commit -a -m "Chagne 4" &&
+	 git push &&
+
+	 sed -i s/44/55/ stuff &&
+	 git commit --amend -a -m "Change 4" &&
+	 test_must_fail git push
+	)
+'
+
+test_expect_failure 'git pull --rebase does not reapply old patches' '
+	(cd dst &&
+	 (git pull --rebase || true) &&
+	 test 3 != $(find .git/rebase-apply -name "000*" | wc -l)
+	)
+'
+
 test_done
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches
  2010-08-06 14:05 [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren
  2010-08-06 14:05 ` [PATCH 1/2] t5520-pull: Add testcases showing spurious conflicts from git " Elijah Newren
@ 2010-08-06 14:05 ` Elijah Newren
  2010-08-08 19:27 ` [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren
  2 siblings, 0 replies; 4+ messages in thread
From: Elijah Newren @ 2010-08-06 14:05 UTC (permalink / raw
  To: git; +Cc: Santi Béjar, gitster, Elijah Newren

Prior to c85c79279df2c8a583d95449d1029baba41f8660, pull --rebase would run
  git rebase $merge_head
which resulted in a call to
  git format-patch ... --ignore-if-in-upstream $merge_head..$cur_branch

This had two nice qualities when upstream isn't rebased: (1) "only" the
patches in $merge_head..$cur_branch would be applied, and (2) patches
could be dropped/ignored if they had already been applied.  But this did
not work well when upstream is rebased, since in that case
$merge_head..$cur_branch refers to too many commits that would need to be
reapplied, and could result in intentionally dropped commits being
reintroduced.

So the algorithm was changed.  Defining $old_remote_ref to be the most
recent entry in the reflog for @upstream that is an ancestor of
$cur_branch, pull --rebase was changed (over time) to run
  git rebase --onto $merge_head $old_remote_ref
which results in a call to
  git format-patch ... --ignore-if-in-upstream $old_remote_ref..$cur_branch

In the rebased upstream case, this can result in far fewer commits being
included in the rebase, though the fact that $old_remote_ref is an ancestor
of $cur_branch means that format-patch will not know what upstream is and
will not be able to determine if any patches are already upstream.

In the non-rebased upstream case, this new form is usually the same as the
original code.  However, as noted above, the --ignore-if-in-upstream flag
becomes meaningless and all patches will be forced to be reapplied.  Also,
$old_remote_ref can be an ancestor of
   $(git merge-base $merge_head $cur_branch)
meaning that pull --rebase may try to reapply more patches which are
clearly already upstream, without the means to detect that they've already
been applied.  This can be extremely confusing for new users ("git is
giving me lots of conflicts in stuff I didn't even change since my last
push.")

Fix the non-rebased upstream case by ignoring $old_remote_ref whenever it
is contained by $(git merge-base $merge_head $cur_branch).

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 git-pull.sh     |   34 ++++++++++++++++++++++------------
 t/t5520-pull.sh |    4 ++--
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/git-pull.sh b/git-pull.sh
index a09a44e..54da07b 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -206,18 +206,6 @@ test true = "$rebase" && {
 		git diff-index --ignore-submodules --cached --quiet HEAD -- ||
 		die "refusing to pull with rebase: your working tree is not up-to-date"
 	fi
-	oldremoteref= &&
-	. git-parse-remote &&
-	remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
-	oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
-	for reflog in $(git rev-list -g $remoteref 2>/dev/null)
-	do
-		if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
-		then
-			oldremoteref="$reflog"
-			break
-		fi
-	done
 }
 orig_head=$(git rev-parse -q --verify HEAD)
 git fetch $verbosity $progress $dry_run --update-head-ok "$@" || exit 1
@@ -273,6 +261,28 @@ then
 	exit
 fi
 
+if test true = "$rebase"
+then
+	oldremoteref= &&
+	. git-parse-remote &&
+	remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
+	oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
+	for reflog in $(git rev-list -g $remoteref 2>/dev/null)
+	do
+		if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
+		then
+			oldremoteref="$reflog"
+			break
+		fi
+	done
+
+	o=$(git show-branch --merge-base $curr_branch $merge_head $oldremoteref)
+	if test "$oldremoteref" = "$o"
+	then
+		unset oldremoteref
+	fi
+fi
+
 merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
 case "$rebase" in
 true)
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 8f76829..4bf2253 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -182,7 +182,7 @@ test_expect_success 'setup for detecting upstreamed changes' '
 	)
 '
 
-test_expect_failure 'git pull --rebase detects upstreamed changes' '
+test_expect_success 'git pull --rebase detects upstreamed changes' '
 	(cd dst &&
 	 git pull --rebase &&
 	 test -z "$(git ls-files -u)"
@@ -212,7 +212,7 @@ test_expect_success 'setup for avoiding reapplying old patches' '
 	)
 '
 
-test_expect_failure 'git pull --rebase does not reapply old patches' '
+test_expect_success 'git pull --rebase does not reapply old patches' '
 	(cd dst &&
 	 (git pull --rebase || true) &&
 	 test 3 != $(find .git/rebase-apply -name "000*" | wc -l)
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] Fix spurious conflicts with pull --rebase
  2010-08-06 14:05 [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren
  2010-08-06 14:05 ` [PATCH 1/2] t5520-pull: Add testcases showing spurious conflicts from git " Elijah Newren
  2010-08-06 14:05 ` [PATCH 2/2] pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches Elijah Newren
@ 2010-08-08 19:27 ` Elijah Newren
  2 siblings, 0 replies; 4+ messages in thread
From: Elijah Newren @ 2010-08-08 19:27 UTC (permalink / raw
  To: git

On Fri, Aug 6, 2010 at 8:05 AM, Elijah Newren <newren@gmail.com> wrote:
> This patch series fixes git pull --rebase failing to detect if "local"
> patches are already upstream in cases where the upstream repository is
> not itself rebased.  Also in the non-rebased upstream case, this
> series avoids checking/applying more patches than needed (i.e. avoids
> having rebase work on commits which are already reachable from
> upstream).
>
> It would be nice to make 'git pull --rebase' able to detect if patches
> being applied are already part of upstream in cases where the upstream
> repository has been rebased.  As far as I can tell, that would require
> changes to format-patch to allow it to be told what 'upstream' is, and
> some changes to git-pull.sh/git-rebase.sh to pass it this information.

I obviously hadn't slept enough when I wrote the above paragraphs;
they don't parse very well.  Sorry about that.  I just posted a new
series, with some wording improvements and minor portability fixes.

(For the benefit of those not following this list, to whom I gave a
direct link to this thread, the updated series is here:
http://thread.gmane.org/gmane.comp.version-control.git/152918)


Elijah

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-08-08 19:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-06 14:05 [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren
2010-08-06 14:05 ` [PATCH 1/2] t5520-pull: Add testcases showing spurious conflicts from git " Elijah Newren
2010-08-06 14:05 ` [PATCH 2/2] pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches Elijah Newren
2010-08-08 19:27 ` [PATCH 0/2] Fix spurious conflicts with pull --rebase Elijah Newren

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).