git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC/PATCH] Give better 'pull' advice when pushing non-ff updates to current branch

From
Christopher Tiwald <christiwald@gmail.com>
Date
Apr 11, 2012, 02:08 UTC
Message-ID
<20120411020816.GU376@gmail.com>
In-Reply-To
<20120406071520.GD25301@sigill.intra.peff.net>
On Fri, Apr 06, 2012 at 03:15:20AM -0400, Jeff King wrote:
Show 14 quoted lines
> So shouldn't the advice for a non-fast-forward push be:
> 
>    if $source_ref is currently checked out
>            advise "git checkout $source_ref, and then..."
>    fi
>    if $dest_remote == branch.$source_ref.remote &&
>       $dest_ref == branch.$source_ref.merge
>            advise "git pull"
>    else
>            advise "git pull $dest_remote $dest_ref"
>    fi
> 
> That handles only one ref, of course. If you get multiple non-ff
> failures, I'm not sure what we should advise.

Hmmm. Maybe something like this? Note to reviewers: This is necessarily based on ct/advise-push-default.

Assuming this logic is sound and the patch is a reasonable change, I'm not wedded to "pushNonFFCurrentUntracked" and "pushNonFFCurrentTracked". I'm concerned both config options are a bit too long. Is there a better, more concise way to specify those config options?

---- >8 ---- Suppose a user configured a local branch to track an upstream branch by a different name or didn't set an upstream branch at all. In these cases, issuing 'git pull' without specifying a remote repository or refspec can be dangerous. In the first case, 'git pull --rebase' could rewrite published history. In the second, 'git pull' without argument will fail.

Modify 'git push's non-fast-forward advice to account for these cases. Instruct users who push a non-fast-forward update to their current branch to 'git pull <repository> <refspec>' when the branch is untracked or tracks to a different repo or refspec then the one they specified. Otherwise, instruct users to 'git pull'. Make both types of advice configurable, so that users who disable one won't disable the other on accident. Finally, offer users who configure a branch for octopus merges, i.e. where 'branch->merge_nr > 1', the simple 'git pull' advice.

Signed-off-by: Christopher Tiwald <christiwald@gmail.com>
---
 Documentation/config.txt |    9 +++++++--
 advice.c                 |    6 ++++--
 advice.h                 |    3 ++-
 builtin/push.c           |   48 +++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index fb386ab..fd72120 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -141,9 +141,14 @@ advice.*::
 		Set this variable to 'false' if you want to disable
 		'pushNonFFCurrent', 'pushNonFFDefault', and
 		'pushNonFFMatching' simultaneously.
-	pushNonFFCurrent::
+	pushNonFFCurrentUntracked::
 		Advice shown when linkgit:git-push[1] fails due to a
-		non-fast-forward update to the current branch.
+		non-fast-forward update to the current branch and that
+		branch doesn't match the tracked remote and refspec.
+	pushNonFFCurrentTracked::
+		Advice shown when linkgit:git-push[1] fails due to a
+		non-fast-forward update to the current branch and that
+		branch matches the tracked remote and refspec.
 	pushNonFFDefault::
 		Advice to set 'push.default' to 'upstream' or 'current'
 		when you ran linkgit:git-push[1] and pushed 'matching
diff --git a/advice.c b/advice.c
index a492eea..828a41b 100644
--- a/advice.c
+++ b/advice.c
@@ -1,7 +1,8 @@
 #include "cache.h"
 
 int advice_push_nonfastforward = 1;
-int advice_push_non_ff_current = 1;
+int advice_push_non_ff_current_untracked = 1;
+int advice_push_non_ff_current_tracked = 1;
 int advice_push_non_ff_default = 1;
 int advice_push_non_ff_matching = 1;
 int advice_status_hints = 1;
@@ -15,7 +16,8 @@ static struct {
 	int *preference;
 } advice_config[] = {
 	{ "pushnonfastforward", &advice_push_nonfastforward },
-	{ "pushnonffcurrent", &advice_push_non_ff_current },
+	{ "pushnonffcurrentuntracked", &advice_push_non_ff_current_untracked },
+	{ "pushnonffcurrenttracked", &advice_push_non_ff_current_tracked },
 	{ "pushnonffdefault", &advice_push_non_ff_default },
 	{ "pushnonffmatching", &advice_push_non_ff_matching },
 	{ "statushints", &advice_status_hints },
diff --git a/advice.h b/advice.h
index f3cdbbf..c18809f 100644
--- a/advice.h
+++ b/advice.h
@@ -4,7 +4,8 @@
 #include "git-compat-util.h"
 
 extern int advice_push_nonfastforward;
-extern int advice_push_non_ff_current;
+extern int advice_push_non_ff_current_untracked;
+extern int advice_push_non_ff_current_tracked;
 extern int advice_push_non_ff_default;
 extern int advice_push_non_ff_matching;
 extern int advice_status_hints;
diff --git a/builtin/push.c b/builtin/push.c
index 8a14e4b..0671d27 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -118,12 +118,18 @@ static void setup_default_push_refspecs(struct remote *remote)
 	}
 }
 
-static const char message_advice_pull_before_push[] =
+static const char message_advice_tracked_pull_before_push[] =
 	N_("Updates were rejected because the tip of your current branch is behind\n"
 	   "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
 	   "before pushing again.\n"
 	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
+static const char message_advice_untracked_pull_before_push[] =
+	N_("Updates were rejected because the tip of your current branch is behind\n"
+	   "its remote counterpart. Merge the remote changes to your local branch\n"
+	   "(e.g. 'git pull <repository> <refspec>') before pushing again.\n"
+	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
+
 static const char message_advice_use_upstream[] =
 	N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 	   "counterpart. If you did not intend to push that branch, you may want to\n"
@@ -136,11 +142,20 @@ static const char message_advice_checkout_pull_push[] =
 	   "(e.g. 'git pull') before pushing again.\n"
 	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
-static void advise_pull_before_push(void)
+static void advise_tracked_pull_before_push(void)
+{
+	if (!advice_push_non_ff_current_tracked ||
+	    !advice_push_nonfastforward)
+		return;
+	advise(_(message_advice_tracked_pull_before_push));
+}
+
+static void advise_untracked_pull_before_push(void)
 {
-	if (!advice_push_non_ff_current || !advice_push_nonfastforward)
+	if (!advice_push_non_ff_current_untracked ||
+	    !advice_push_nonfastforward)
 		return;
-	advise(_(message_advice_pull_before_push));
+	advise(_(message_advice_untracked_pull_before_push));
 }
 
 static void advise_use_upstream(void)
@@ -161,6 +176,16 @@ static int push_with_options(struct transport *transport, int flags)
 {
 	int err;
 	int nonfastforward;
+	struct branch *branch;
+	struct strbuf buf = STRBUF_INIT;
+
+	branch = branch_get(NULL);
+
+	if (branch) {
+		strbuf_addstr(&buf, transport->remote->name);
+		strbuf_addstr(&buf, "/");
+		strbuf_addstr(&buf, branch->name);
+	}
 
 	transport_set_verbosity(transport, verbosity, progress);
 
@@ -185,7 +210,18 @@ static int push_with_options(struct transport *transport, int flags)
 	default:
 		break;
 	case NON_FF_HEAD:
-		advise_pull_before_push();
+		/* Branches configured for octopus merges should advise
+		 * just 'git pull' */
+		if (branch->remote_name &&
+		    branch->merge &&
+		    branch->merge_nr == 1 &&
+		    !strcmp(transport->remote->name, branch->remote_name) &&
+		    !strcmp(strbuf_detach(&buf, NULL),
+			    prettify_refname(branch->merge[0]->dst))) {
+			advise_tracked_pull_before_push();
+		}
+		else
+			advise_untracked_pull_before_push();
 		break;
 	case NON_FF_OTHER:
 		if (default_matching_used)
@@ -195,6 +231,8 @@ static int push_with_options(struct transport *transport, int flags)
 		break;
 	}
 
+	strbuf_release(&buf);
+
 	return 1;
 }
 
-- 
1.7.10.4.g2c970.dirty
Previous: Matthieu MoyNext: Dmitry Potapov
Message 140 of 152 in “[ANNOUNCE] Git 1.7.10-rc3”
  1. Junio C HamanoMar 28, 2012
  2. Jeff KingMar 29, 2012
  3. Junio C HamanoMar 29, 2012
  4. Jeff KingMar 29, 2012
  5. Junio C HamanoMar 30, 2012
  6. push.default: current vs upstreamJeff King, Mar 30, 2012
  7. Junio C HamanoMar 30, 2012
  8. Jeff KingMar 30, 2012
  9. Junio C HamanoMar 30, 2012
  10. Jeff KingMar 30, 2012
  11. Junio C HamanoMar 30, 2012
  12. Jeff KingMar 30, 2012
  13. Junio C HamanoMar 30, 2012
  14. Nathan GrayMar 31, 2012
  15. Seth RobertsonMar 31, 2012
  16. Junio C HamanoApr 1, 2012
  17. Nathan GrayApr 1, 2012
  18. Matthieu MoyApr 2, 2012
  19. Junio C HamanoApr 2, 2012
  20. Matthieu MoyApr 2, 2012
  21. Junio C HamanoApr 2, 2012
  22. Matthieu MoyApr 2, 2012
  23. Junio C HamanoApr 2, 2012
  24. Matthieu MoyApr 2, 2012
  25. Junio C HamanoApr 2, 2012
  26. demerphqApr 2, 2012
  27. Matthieu MoyApr 2, 2012
  28. demerphqApr 4, 2012
  29. Jeff KingApr 5, 2012
  30. Matthieu MoyApr 5, 2012
  31. Jeff KingApr 6, 2012
  32. Matthieu MoyApr 6, 2012
  33. Jeff KingApr 6, 2012
  34. Junio C HamanoApr 6, 2012
  35. Jehan BingApr 6, 2012
  36. Michael HaggertyApr 7, 2012
  37. Jeff KingApr 7, 2012
  38. Andrew SayersApr 7, 2012
  39. Jeff KingApr 12, 2012
  40. Junio C HamanoApr 12, 2012
  41. Andrew SayersApr 12, 2012
  42. Junio C HamanoApr 12, 2012
  43. Jeff KingApr 12, 2012
  44. Philip OakleyApr 12, 2012
  45. Junio C HamanoApr 13, 2012
  46. Andrew SayersApr 17, 2012
  47. Junio C HamanoApr 8, 2012
  48. Matthieu MoyApr 11, 2012
  49. Junio C HamanoApr 11, 2012
  50. Jeff KingApr 12, 2012
  51. Matthieu MoyApr 12, 2012
  52. Jeff KingApr 12, 2012
  53. Matthieu MoyApr 12, 2012
  54. Junio C HamanoApr 12, 2012
  55. Junio C HamanoApr 19, 2012
  56. Matthieu MoyApr 19, 2012
  57. Junio C HamanoApr 19, 2012
  58. 0/3 push.default upcomming changeMatthieu Moy, Apr 19, 2012
  59. 1/3 push: introduce new push.default mode "simple"Matthieu Moy, Apr 19, 2012
  60. Jeff KingApr 19, 2012
  61. Matthieu MoyApr 20, 2012
  62. 0/4 push.default upcomming changeMatthieu Moy, Apr 20, 2012
  63. 1/4 Documentation: explain push.default option a bit moreMatthieu Moy, Apr 20, 2012
  64. Jeff KingApr 20, 2012
  65. Junio C HamanoApr 20, 2012
  66. Michael HaggertyApr 21, 2012
  67. Junio C HamanoApr 21, 2012
  68. Michael HaggertyApr 21, 2012
  69. Junio C HamanoApr 21, 2012
  70. 2/4 push: introduce new push.default mode "simple"Matthieu Moy, Apr 20, 2012
  71. Jeff KingApr 20, 2012
  72. Zbigniew Jędrzejewski-SzmekApr 22, 2012
  73. Junio C HamanoApr 20, 2012
  74. Matthieu MoyApr 23, 2012
  75. 3/4 t5570: use explicit push refspecMatthieu Moy, Apr 20, 2012
  76. 4/4 push: start warning upcoming default change for push.defaultMatthieu Moy, Apr 20, 2012
  77. Jeff KingApr 20, 2012
  78. Matthieu MoyApr 22, 2012
  79. Junio C HamanoApr 23, 2012
  80. 0/7 push.default upcomming changeMatthieu Moy, Apr 23, 2012
  81. 1/7 Documentation: explain push.default option a bit moreMatthieu Moy, Apr 23, 2012
  82. Junio C HamanoApr 23, 2012
  83. Philip OakleyApr 23, 2012
  84. Junio C HamanoApr 23, 2012
  85. Philip OakleyApr 23, 2012
  86. 2/7 Undocument deprecated alias 'push.default=tracking'Matthieu Moy, Apr 23, 2012
  87. Junio C HamanoApr 23, 2012
  88. Ævar Arnfjörð BjarmasonJan 31, 2013
  89. Junio C HamanoJan 31, 2013
  90. Jonathan NiederJan 31, 2013
  91. Jonathan NiederJan 31, 2013
  92. Junio C HamanoJan 31, 2013
  93. Junio C HamanoJan 31, 2013
  94. Jonathan NiederJan 31, 2013
  95. Junio C HamanoJan 31, 2013
  96. Jonathan NiederJan 31, 2013
  97. Junio C HamanoJan 31, 2013
  98. Junio C HamanoJan 31, 2013
  99. Jonathan NiederJan 31, 2013
  100. Matthieu MoyJan 31, 2013
  101. Junio C HamanoJan 31, 2013
  102. Junio C HamanoJan 31, 2013
  103. Jonathan NiederJan 31, 2013
  104. Junio C HamanoFeb 1, 2013
  105. Jonathan NiederJan 31, 2013
  106. Philip OakleyJan 31, 2013
  107. 3/7 t5528-push-default.sh: add helper functionsMatthieu Moy, Apr 23, 2012
  108. Junio C HamanoApr 23, 2012
  109. Matthieu MoyApr 23, 2012
  110. Junio C HamanoApr 23, 2012
  111. Matthieu MoyApr 23, 2012
  112. Matthieu MoyApr 23, 2012
  113. Junio C HamanoApr 23, 2012
  114. Junio C HamanoApr 23, 2012
  115. 2/3 fixup! t5528-push-default.sh: add helper functionsJunio C Hamano, Apr 23, 2012
  116. 3/3 push: suggested updates to push configuration documentationJunio C Hamano, Apr 23, 2012
  117. 4/7 push: introduce new push.default mode "simple"Matthieu Moy, Apr 23, 2012
  118. Michael HaggertyApr 23, 2012
  119. Matthieu MoyApr 23, 2012
  120. Junio C HamanoApr 23, 2012
  121. Matthieu MoyApr 23, 2012
  122. 5/7 t5570: use explicit push refspecMatthieu Moy, Apr 23, 2012
  123. 6/7 push: document the future default change for push.default (matching -> simple)Matthieu Moy, Apr 23, 2012
  124. 7/7 push: start warning upcoming default change for push.defaultMatthieu Moy, Apr 23, 2012
  125. 0/7 push.default upcomming changeMatthieu Moy, Apr 24, 2012
  126. 1/7 Documentation: explain push.default option a bit moreMatthieu Moy, Apr 24, 2012
  127. 2/7 Undocument deprecated alias 'push.default=tracking'Matthieu Moy, Apr 24, 2012
  128. 3/7 t5528-push-default.sh: add helper functionsMatthieu Moy, Apr 24, 2012
  129. 4/7 push: introduce new push.default mode "simple"Matthieu Moy, Apr 24, 2012
  130. Junio C HamanoApr 25, 2012
  131. Matthieu MoyApr 25, 2012
  132. 5/7 t5570: use explicit push refspecMatthieu Moy, Apr 24, 2012
  133. 6/7 push: document the future default change for push.default (matching -> simple)Matthieu Moy, Apr 24, 2012
  134. 7/7 push: start warning upcoming default change for push.defaultMatthieu Moy, Apr 24, 2012
  135. Junio C HamanoApr 24, 2012
  136. 2/3 t5570: use explicit push refspecMatthieu Moy, Apr 19, 2012
  137. 3/3 push: start warning upcoming default change for push.defaultMatthieu Moy, Apr 19, 2012
  138. t5541: warning message is given even with --quietJunio C Hamano, Apr 26, 2012
  139. Matthieu MoyApr 26, 2012
  140. Give better 'pull' advice when pushing non-ff updates to current branchChristopher Tiwald, Apr 11, 2012
  141. Dmitry PotapovApr 6, 2012
  142. demerphqApr 6, 2012
  143. Dmitry PotapovApr 6, 2012
  144. demerphqApr 6, 2012
  145. Dmitry PotapovApr 6, 2012
  146. Junio C HamanoMar 30, 2012
  147. Jeff KingApr 3, 2012
  148. Jeff KingApr 3, 2012
  149. Junio C HamanoApr 3, 2012
  150. Junio C HamanoApr 3, 2012
  151. Jeff KingApr 5, 2012
  152. Felipe ContrerasApr 8, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.