All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] branch, config:  teach branch.autosetuprebase about 'merges' mode
@ 2021-01-20  0:20 Alex Reed via GitGitGadget
  0 siblings, 0 replies; only message in thread
From: Alex Reed via GitGitGadget @ 2021-01-20  0:20 UTC (permalink / raw)
  To: git; +Cc: Alex Reed, Alex Reed

From: Alex Reed <acreed4@gmail.com>

branch.autoSetupRebase now honors the 'merges' flag, allowing tracking branches
to be auto-populated with 'branch.<name>.rebase = merges'.  This allows complex
workflows to more easily retain non-trivial merges while rebasing branches on
pull operations.  Seeding new branches with 'branch.<name>.rebase = true' is not
always sufficient (read: not project default) and requiring developers to
manually reconfigure every new branch is cumbersome and error-prone.

Signed-off-by: Alex Reed <acreed4@gmail.com>
---
    branch, config: teach branch.autosetuprebase about 'merges' mode
    
    branch.autoSetupRebase now honors the 'merges' flag, allowing tracking
    branches to be auto-populated with 'branch..rebase = merges'. This
    allows complex workflows to more easily retain non-trivial merges while
    rebasing branches on pull operations. Seeding new branches with
    'branch..rebase = true' is not always sufficient (read: not project
    default) and requiring developers to manually reconfigure every new
    branch is cumbersome and error-prone.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-948%2Facr4%2Fautosetuprebase-merges-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-948/acr4/autosetuprebase-merges-v1
Pull-Request: https://github.com/git/git/pull/948

 Documentation/config/branch.txt |  2 +
 branch.c                        | 70 ++++++++++++++++++++-------------
 cache.h                         |  3 +-
 config.c                        |  2 +
 t/t3200-branch.sh               | 45 +++++++++++++++++++++
 t/t5601-clone.sh                | 14 ++++++-
 6 files changed, 107 insertions(+), 29 deletions(-)

diff --git a/Documentation/config/branch.txt b/Documentation/config/branch.txt
index cc5f3249fc5..98410bf003f 100644
--- a/Documentation/config/branch.txt
+++ b/Documentation/config/branch.txt
@@ -21,6 +21,8 @@ branch.autoSetupRebase::
 	remote-tracking branches.
 	When `always`, rebase will be set to true for all tracking
 	branches.
+	When `merges`, rebase will be set to `merges` for all tracking
+	branches.
 	See "branch.autoSetupMerge" for details on how to set up a
 	branch to track another branch.
 	This option defaults to never.
diff --git a/branch.c b/branch.c
index 9c9dae1eae3..b197fe0bbb3 100644
--- a/branch.c
+++ b/branch.c
@@ -34,17 +34,25 @@ static int find_tracked_branch(struct remote *remote, void *priv)
 	return 0;
 }
 
-static int should_setup_rebase(const char *origin)
+typedef enum {
+	REBASE_FALSE,
+	REBASE_TRUE,
+	REBASE_MERGES
+} rebase_type;
+
+static rebase_type should_setup_rebase(const char *origin)
 {
 	switch (autorebase) {
 	case AUTOREBASE_NEVER:
-		return 0;
+		return REBASE_FALSE;
 	case AUTOREBASE_LOCAL:
-		return origin == NULL;
+		return origin == NULL ? REBASE_TRUE : REBASE_FALSE;
 	case AUTOREBASE_REMOTE:
-		return origin != NULL;
+		return origin != NULL ? REBASE_TRUE : REBASE_FALSE;
 	case AUTOREBASE_ALWAYS:
-		return 1;
+		return REBASE_TRUE;
+	case AUTOREBASE_MERGES:
+		return REBASE_MERGES;
 	}
 	return 0;
 }
@@ -59,7 +67,8 @@ int install_branch_config(int flag, const char *local, const char *origin, const
 {
 	const char *shortname = NULL;
 	struct strbuf key = STRBUF_INIT;
-	int rebasing = should_setup_rebase(origin);
+	rebase_type rebasing = should_setup_rebase(origin);
+	struct strbuf method = STRBUF_INIT;
 
 	if (skip_prefix(remote, "refs/heads/", &shortname)
 	    && !strcmp(local, shortname)
@@ -78,44 +87,51 @@ int install_branch_config(int flag, const char *local, const char *origin, const
 	if (git_config_set_gently(key.buf, remote) < 0)
 		goto out_err;
 
-	if (rebasing) {
-		strbuf_reset(&key);
-		strbuf_addf(&key, "branch.%s.rebase", local);
-		if (git_config_set_gently(key.buf, "true") < 0)
-			goto out_err;
+	strbuf_reset(&key);
+	strbuf_addf(&key, "branch.%s.rebase", local);
+	switch(rebasing) {
+		case REBASE_TRUE:
+			strbuf_addstr(&method, " by rebasing");
+			if(git_config_set_gently(key.buf, "true") < 0)
+				goto out_err;
+			break;
+		case REBASE_MERGES:
+			strbuf_addstr(&method, " by rebasing while preserving merges");
+			if (git_config_set_gently(key.buf, "merges") < 0)
+				goto out_err;
+			break;
+    default:;
 	}
 	strbuf_release(&key);
 
 	if (flag & BRANCH_CONFIG_VERBOSE) {
 		if (shortname) {
 			if (origin)
-				printf_ln(rebasing ?
-					  _("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") :
-					  _("Branch '%s' set up to track remote branch '%s' from '%s'."),
-					  local, shortname, origin);
+				printf_ln(
+					_("Branch '%s' set up to track remote branch '%s' from '%s'%s."),
+					local, shortname, origin, method.buf);
 			else
-				printf_ln(rebasing ?
-					  _("Branch '%s' set up to track local branch '%s' by rebasing.") :
-					  _("Branch '%s' set up to track local branch '%s'."),
-					  local, shortname);
+				printf_ln(
+					_("Branch '%s' set up to track local branch '%s'%s."),
+					local, shortname, method.buf);
 		} else {
 			if (origin)
-				printf_ln(rebasing ?
-					  _("Branch '%s' set up to track remote ref '%s' by rebasing.") :
-					  _("Branch '%s' set up to track remote ref '%s'."),
-					  local, remote);
+				printf_ln(
+					_("Branch '%s' set up to track remote ref '%s'%s."),
+					local, remote, method.buf);
 			else
-				printf_ln(rebasing ?
-					  _("Branch '%s' set up to track local ref '%s' by rebasing.") :
-					  _("Branch '%s' set up to track local ref '%s'."),
-					  local, remote);
+				printf_ln(
+					_("Branch '%s' set up to track local ref '%s'%s."),
+					local, remote, method.buf);
 		}
 	}
 
+	strbuf_release(&method);
 	return 0;
 
 out_err:
 	strbuf_release(&key);
+	strbuf_release(&method);
 	error(_("Unable to write upstream branch configuration"));
 
 	advise(_(tracking_advice),
diff --git a/cache.h b/cache.h
index eefa93b08f8..5a378bcd534 100644
--- a/cache.h
+++ b/cache.h
@@ -995,7 +995,8 @@ enum rebase_setup_type {
 	AUTOREBASE_NEVER = 0,
 	AUTOREBASE_LOCAL,
 	AUTOREBASE_REMOTE,
-	AUTOREBASE_ALWAYS
+	AUTOREBASE_ALWAYS,
+	AUTOREBASE_MERGES
 };
 
 enum push_default_type {
diff --git a/config.c b/config.c
index 4c0cf3a1c15..28d813f2595 100644
--- a/config.c
+++ b/config.c
@@ -1443,6 +1443,8 @@ static int git_default_branch_config(const char *var, const char *value)
 			autorebase = AUTOREBASE_REMOTE;
 		else if (!strcmp(value, "always"))
 			autorebase = AUTOREBASE_ALWAYS;
+		else if (!strcmp(value, "merges"))
+			autorebase = AUTOREBASE_MERGES;
 		else
 			return error(_("malformed value for %s"), var);
 		return 0;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 0af3b85d172..056192f72c5 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -1222,6 +1222,51 @@ test_expect_success 'autosetuprebase always on an untracked remote branch' '
 	test "z$(git config branch.myr20.rebase)" = z
 '
 
+test_expect_success 'autosetuprebase merges on a tracked local branch' '
+	git config branch.autosetuprebase merges &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/o || git fetch local) &&
+	git branch mybase21 &&
+	git branch --track myr21 mybase3 &&
+	test "$(git config branch.myr21.remote)" = . &&
+	test "$(git config branch.myr21.merge)" = refs/heads/mybase3 &&
+	test "$(git config branch.myr21.rebase)" = merges
+'
+
+test_expect_success 'autosetuprebase merges on a tracked remote branch' '
+	git config branch.autosetuprebase merges &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/main || git fetch local) &&
+	git branch --track myr22 local/main &&
+	test "$(git config branch.myr22.remote)" = local &&
+	test "$(git config branch.myr22.merge)" = refs/heads/main &&
+	test "$(git config branch.myr22.rebase)" = merges
+'
+
+test_expect_success 'autosetuprebase merges on an untracked local branch' '
+	git config branch.autosetuprebase merges &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/main || git fetch local) &&
+	git branch --no-track myr23 mybase2 &&
+	test "z$(git config branch.myr23.remote)" = z &&
+	test "z$(git config branch.myr23.merge)" = z &&
+	test "z$(git config branch.myr23.rebase)" = z
+'
+
+test_expect_success 'autosetuprebase merges on an untracked remote branch' '
+	git config branch.autosetuprebase merges &&
+	git config remote.local.url . &&
+	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+	(git show-ref -q refs/remotes/local/main || git fetch local) &&
+	git branch --no-track myr24 local/main &&
+	test "z$(git config branch.myr24.remote)" = z &&
+	test "z$(git config branch.myr24.merge)" = z &&
+	test "z$(git config branch.myr24.rebase)" = z
+'
+
 test_expect_success 'autosetuprebase always on detached HEAD' '
 	git config branch.autosetupmerge always &&
 	test_when_finished git checkout main &&
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 7df3c5373ae..10983191439 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -210,7 +210,7 @@ test_expect_success 'clone a void' '
 	test_cmp target-6/.git/config target-7/.git/config
 '
 
-test_expect_success 'clone respects global branch.autosetuprebase' '
+test_expect_success 'clone respects global branch.autosetuprebase remote' '
 	(
 		test_config="$HOME/.gitconfig" &&
 		git config -f "$test_config" branch.autosetuprebase remote &&
@@ -222,6 +222,18 @@ test_expect_success 'clone respects global branch.autosetuprebase' '
 	)
 '
 
+test_expect_success 'clone respects global branch.autosetuprebase merges' '
+	(
+		test_config="$HOME/.gitconfig" &&
+		git config -f "$test_config" branch.autosetuprebase merges &&
+		rm -fr dst &&
+		git clone src dst &&
+		cd dst &&
+		actual="z$(git config branch.master.rebase)" &&
+		test zmerges = $actual
+	)
+'
+
 test_expect_success 'respect url-encoding of file://' '
 	git init x+y &&
 	git clone "file://$PWD/x+y" xy-url-1 &&

base-commit: 66e871b6647ffea61a77a0f82c7ef3415f1ee79c
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2021-01-20  0:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-20  0:20 [PATCH] branch, config: teach branch.autosetuprebase about 'merges' mode Alex Reed via GitGitGadget

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.