Skip to content

Commit 4803f20

Browse files
HaraldNordgrengitster
authored andcommitted
branch: add branch.<name>.deleteMerged opt-out
Setting branch.<name>.deleteMerged=false exempts that branch from "git branch --delete-merged", which is useful for a topic you want to keep developing after an early round of it has been merged upstream. Unless --quiet is given, each skip is reported so the user knows why their topic was kept. Explicit deletion with "git branch -d" still uses the normal merge check and ignores this setting. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 0abb528 commit 4803f20

4 files changed

Lines changed: 60 additions & 2 deletions

File tree

Documentation/config/branch.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,10 @@ for details).
102102
`git branch --edit-description`. Branch description is
103103
automatically added to the `format-patch` cover letter or
104104
`request-pull` summary.
105+
106+
`branch.<name>.deleteMerged`::
107+
If set to `false`, branch _<name>_ is exempt from
108+
`git branch --delete-merged`. Useful for a topic branch you
109+
intend to develop further after an initial round has been
110+
merged upstream. Defaults to true. Explicit deletion via
111+
`git branch -d` is unaffected.

Documentation/git-branch.adoc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,12 @@ A branch is not deleted when:
216216
+
217217
--
218218
* its configured upstream ref no longer exists,
219-
* it is checked out in any worktree, or
219+
* it is checked out in any worktree,
220220
* pushing it by name to the remote configured by
221221
`branch.<name>.remote` would update its upstream, so it cannot be
222222
distinguished from a branch that just looks "fully merged" right
223-
after a pull.
223+
after a pull, or
224+
* `branch.<name>.deleteMerged` is set to `false`.
224225
--
225226
+
226227
A branch whose work has not yet been merged into its upstream is

builtin/branch.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ static int delete_merged_branches(const struct strvec *upstreams,
786786
struct ref_array candidates = { 0 };
787787
struct strset deletable_branch_names = STRSET_INIT;
788788
struct strvec branches_to_delete = STRVEC_INIT;
789+
struct strbuf key = STRBUF_INIT;
789790
struct hashmap_iter iter;
790791
struct strmap_entry *entry;
791792
size_t i;
@@ -805,6 +806,7 @@ static int delete_merged_branches(const struct strvec *upstreams,
805806
const char *branch_name;
806807
struct branch *branch;
807808
const char *upstream_refname;
809+
int opt_out;
808810

809811
if (!skip_prefix(branch_refname, "refs/heads/", &branch_name))
810812
BUG("filter returned non-branch ref '%s'", branch_refname);
@@ -822,6 +824,17 @@ static int delete_merged_branches(const struct strvec *upstreams,
822824
FILTER_REFS_BRANCHES, DELETE_BRANCH_SKIP_UNMERGED))
823825
continue;
824826

827+
strbuf_reset(&key);
828+
strbuf_addf(&key, "branch.%s.deletemerged", branch_name);
829+
if (!repo_config_get_bool(the_repository, key.buf, &opt_out) &&
830+
!opt_out) {
831+
if (!(flags & DELETE_BRANCH_QUIET))
832+
fprintf(stderr,
833+
_("Skipping '%s' (branch.%s.deleteMerged is false)\n"),
834+
branch_name, branch_name);
835+
continue;
836+
}
837+
825838
strset_add(&deletable_branch_names, branch_name);
826839
}
827840

@@ -837,6 +850,7 @@ static int delete_merged_branches(const struct strvec *upstreams,
837850
DELETE_BRANCH_NO_HEAD_FALLBACK |
838851
flags);
839852

853+
strbuf_release(&key);
840854
strvec_clear(&branches_to_delete);
841855
strset_clear(&deletable_branch_names);
842856
ref_array_clear(&candidates);

t/t3200-branch.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,4 +2038,40 @@ test_expect_success '--delete-merged requires a value' '
20382038
test_must_fail git -C forked branch --delete-merged 2>err &&
20392039
test_grep "requires a value" err
20402040
'
2041+
2042+
test_expect_success '--delete-merged honours branch.<name>.deleteMerged=false' '
2043+
setup_repo_for_delete_merged &&
2044+
create_merged_branch deleted &&
2045+
create_merged_branch kept &&
2046+
(
2047+
cd repo &&
2048+
git config branch.kept.deleteMerged false &&
2049+
git checkout --detach &&
2050+
2051+
git branch --delete-merged origin/next 2>err &&
2052+
2053+
test_grep "Skipping .kept." err &&
2054+
check_branches <<-\EOF
2055+
kept
2056+
main
2057+
EOF
2058+
)
2059+
'
2060+
2061+
test_expect_success "branch -d still deletes a deleteMerged=false branch" '
2062+
setup_repo_for_delete_merged &&
2063+
create_merged_branch kept &&
2064+
(
2065+
cd repo &&
2066+
git config branch.kept.deleteMerged false &&
2067+
git checkout --detach &&
2068+
2069+
git branch -d kept &&
2070+
2071+
check_branches <<-\EOF
2072+
main
2073+
EOF
2074+
)
2075+
'
2076+
20412077
test_done

0 commit comments

Comments
 (0)