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

[PATCH 2/2] branch: clear target branch configuration before copying or renaming

From
Rubén Justo <rjusto@gmail.com>
Date
Nov 17, 2022, 01:44 UTC
Message-ID
<762c1e8f-fd0c-3b4b-94a0-709d8c9431e4@gmail.com>
In-Reply-To
<f0b2d46c-2e9c-2630-2870-8ed550dd1606@gmail.com>
There are two problems with -m (rename) and -c (copy) branch operations.
 1. If we force-rename or force-copy a branch to overwrite another
 branch that already has configuration, the resultant branch ends up
 with the source configuration (if any) mixed with the configuration for
 the overwritten branch.
	$ git branch upstream
	$ git branch -t foo upstream  # foo has tracking configuration
	$ git branch bar              # bar has not
	$ git branch -M bar foo       # force-rename bar to foo
	$ git config branch.foo.merge # must return clear
	refs/heads/upstream
 2. If we repeatedly force-copy a branch to the same name, the branch
 configuration is repeatedly copied each time.
	$ git branch upstream
	$ git branch -t foo upstream  # foo has tracking configuration
	$ git branch -c foo bar       # bar is a copy of foo
	$ git branch -C foo bar       # again
	$ git branch -C foo bar       # ..
	$ git config --get-all branch.bar.merge # must return one value
	refs/heads/upstream
	refs/heads/upstream
	refs/heads/upstream

Whenever we copy or move (forced or not) we must make sure that there is no residual configuration that will be, probably erroneously, inherited by the new branch. To avoid confusions, clear any branch configuration before setting the configuration from the copied or moved branch.

Signed-off-by: Rubén Justo <rjusto@gmail.com>
---
 builtin/branch.c  | 17 +++++++++++------
 t/t3200-branch.sh | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index a35e174aae..14664f0278 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -583,12 +583,17 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 
 	strbuf_release(&logmsg);
 
-	strbuf_addf(&oldsection, "branch.%s", interpreted_oldname);
-	strbuf_addf(&newsection, "branch.%s", interpreted_newname);
-	if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
-		die(_("Branch is renamed, but update of config-file failed"));
-	if (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
-		die(_("Branch is copied, but update of config-file failed"));
+	if (strcmp(interpreted_oldname, interpreted_newname)) {
+		strbuf_addf(&oldsection, "branch.%s", interpreted_oldname);
+		strbuf_addf(&newsection, "branch.%s", interpreted_newname);
+
+		delete_branch_config(interpreted_newname);
+
+		if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
+			die(_("Branch is renamed, but update of config-file failed"));
+		if (copy && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
+			die(_("Branch is copied, but update of config-file failed"));
+	}
 	strbuf_release(&oldref);
 	strbuf_release(&newref);
 	strbuf_release(&oldsection);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 7f605f865b..c3b3d11c28 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -218,6 +218,25 @@ test_expect_success 'git branch -M should leave orphaned HEAD alone' '
 	)
 '
 
+test_expect_success 'git branch -M inherites clean tracking setup' '
+	test_when_finished git branch -D moved &&
+	git branch -t main-tracked main &&
+	git branch non-tracked &&
+	git branch -M main-tracked moved &&
+	git branch --unset-upstream moved &&
+	git branch -M non-tracked moved &&
+	test_must_fail git branch --unset-upstream moved
+'
+
+test_expect_success 'git branch -C inherites clean tracking setup' '
+	test_when_finished git branch -D copiable copied &&
+	git branch -t copiable main &&
+	git branch -C copiable copied &&
+	git branch --unset-upstream copied &&
+	git branch -C copied copiable &&
+	test_must_fail git branch --unset-upstream copiable
+'
+
 test_expect_success 'resulting reflog can be shown by log -g' '
 	oid=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-- 
2.36.1
Previous: Rubén JustoNext: Victoria Dye
Message 7 of 15 in “branch: fix some malfunctions in -m/-c”
  1. 0/2 branch: fix some malfunctions in -m/-cRubén Justo, Nov 17, 2022
  2. 1/2 branch: force-copy a branch to itself via @{-1} is a no-opRubén Justo, Nov 17, 2022
  3. Victoria DyeNov 17, 2022
  4. Rubén JustoNov 20, 2022
  5. Ævar Arnfjörð BjarmasonNov 18, 2022
  6. Rubén JustoNov 20, 2022
  7. 2/2 branch: clear target branch configuration before copying or renamingRubén Justo, Nov 17, 2022
  8. Victoria DyeNov 18, 2022
  9. Rubén JustoNov 20, 2022
  10. Victoria DyeNov 20, 2022
  11. Rubén JustoNov 21, 2022
  12. Ævar Arnfjörð BjarmasonNov 18, 2022
  13. Victoria DyeNov 18, 2022
  14. Ævar Arnfjörð BjarmasonNov 18, 2022
  15. Rubén JustoNov 20, 2022

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.