]> git.ipfire.org Git - thirdparty/git.git/commitdiff
rebase-merges: try and use branch names as labels
authorNicolas Guichard <nicolas@guichard.eu>
Wed, 9 Oct 2024 07:58:20 +0000 (07:58 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 9 Oct 2024 17:52:46 +0000 (10:52 -0700)
When interactively rebasing merge commits, the commit message is parsed to
extract a probably meaningful label name. For instance if the merge commit
is “Merge branch 'feature0'”, then the rebase script will have thes lines:
```
label feature0

merge -C $sha feature0 # “Merge branch 'feature0'
```

This heuristic fails in the case of octopus merges or when the merge commit
message is actually unrelated to the parent commits.

An example that combines both is:
```
*---.   967bfa4 (HEAD -> integration) Integration
|\ \ \
| | | * 2135be1 (feature2, feat2) Feature 2
| |_|/
|/| |
| | * c88b01a Feature 1
| |/
|/|
| * 75f3139 (feat0) Feature 0
|/
25c86d0 (main) Initial commit
```
yields the labels Integration, Integration-2 and Integration-3.

Fix this by using a branch name for each merge commit's parent that is the
tip of at least one branch, and falling back to a label derived from the
merge commit message otherwise.
In the example above, the labels become feat0, Integration and feature2.

Signed-off-by: Nicolas Guichard <nicolas@guichard.eu>
Acked-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sequencer.c
t/t3404-rebase-interactive.sh
t/t3430-rebase-merges.sh

index 97959036b50498a43ee4867e526496b8e6698fd8..353d804999b88d5fd5dcf1254d80781f20e62f2e 100644 (file)
@@ -5819,7 +5819,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
        int root_with_onto = flags & TODO_LIST_ROOT_WITH_ONTO;
        int skipped_commit = 0;
        struct strbuf buf = STRBUF_INIT, oneline = STRBUF_INIT;
-       struct strbuf label = STRBUF_INIT;
+       struct strbuf label_from_message = STRBUF_INIT;
        struct commit_list *commits = NULL, **tail = &commits, *iter;
        struct commit_list *tips = NULL, **tips_tail = &tips;
        struct commit *commit;
@@ -5842,6 +5842,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
        oidmap_init(&state.commit2label, 0);
        hashmap_init(&state.labels, labels_cmp, NULL, 0);
        strbuf_init(&state.buf, 32);
+       load_branch_decorations();
 
        if (revs->cmdline.nr && (revs->cmdline.rev[0].flags & BOTTOM)) {
                struct labels_entry *onto_label_entry;
@@ -5902,18 +5903,18 @@ static int make_script_with_merges(struct pretty_print_context *pp,
                        continue;
                }
 
-               /* Create a label */
-               strbuf_reset(&label);
+               /* Create a label from the commit message */
+               strbuf_reset(&label_from_message);
                if (skip_prefix(oneline.buf, "Merge ", &p1) &&
                    (p1 = strchr(p1, '\'')) &&
                    (p2 = strchr(++p1, '\'')))
-                       strbuf_add(&label, p1, p2 - p1);
+                       strbuf_add(&label_from_message, p1, p2 - p1);
                else if (skip_prefix(oneline.buf, "Merge pull request ",
                                     &p1) &&
                         (p1 = strstr(p1, " from ")))
-                       strbuf_addstr(&label, p1 + strlen(" from "));
+                       strbuf_addstr(&label_from_message, p1 + strlen(" from "));
                else
-                       strbuf_addbuf(&label, &oneline);
+                       strbuf_addbuf(&label_from_message, &oneline);
 
                strbuf_reset(&buf);
                strbuf_addf(&buf, "%s -C %s",
@@ -5921,6 +5922,14 @@ static int make_script_with_merges(struct pretty_print_context *pp,
 
                /* label the tips of merged branches */
                for (; to_merge; to_merge = to_merge->next) {
+                       const char *label = label_from_message.buf;
+                       const struct name_decoration *decoration =
+                               get_name_decoration(&to_merge->item->object);
+
+                       if (decoration)
+                               skip_prefix(decoration->name, "refs/heads/",
+                                           &label);
+
                        oid = &to_merge->item->object.oid;
                        strbuf_addch(&buf, ' ');
 
@@ -5933,7 +5942,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
                        tips_tail = &commit_list_insert(to_merge->item,
                                                        tips_tail)->next;
 
-                       strbuf_addstr(&buf, label_oid(oid, label.buf, &state));
+                       strbuf_addstr(&buf, label_oid(oid, label, &state));
                }
                strbuf_addf(&buf, " # %s", oneline.buf);
 
@@ -6041,7 +6050,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
        free_commit_list(commits);
        free_commit_list(tips);
 
-       strbuf_release(&label);
+       strbuf_release(&label_from_message);
        strbuf_release(&oneline);
        strbuf_release(&buf);
 
index f171af3061db9538aa0291e642530e098bff7124..4896a801ee28d2273478d22a3a40a1694ef42c81 100755 (executable)
@@ -1870,7 +1870,7 @@ test_expect_success '--update-refs adds commands with --rebase-merges' '
                pick $(git log -1 --format=%h branch2~1) F
                pick $(git log -1 --format=%h branch2) I
                update-ref refs/heads/branch2
-               label merge
+               label branch2
                reset onto
                pick $(git log -1 --format=%h refs/heads/second) J
                update-ref refs/heads/second
@@ -1881,7 +1881,7 @@ test_expect_success '--update-refs adds commands with --rebase-merges' '
                update-ref refs/heads/third
                pick $(git log -1 --format=%h HEAD~2) M
                update-ref refs/heads/no-conflict-branch
-               merge -C $(git log -1 --format=%h HEAD~1) merge # merge
+               merge -C $(git log -1 --format=%h HEAD~1) branch2 # merge
                update-ref refs/heads/merge-branch
                EOF
 
index 2aa8593f77af91ad5e358c090eae8c98acc43d39..cb891eeb5fd112bf94e31a2158a5dce7990e36e2 100755 (executable)
@@ -108,19 +108,19 @@ test_expect_success 'generate correct todo list' '
 
        reset onto
        pick $b B
-       label E
+       label first
 
        reset onto
        pick $c C
        label branch-point
        pick $f F
        pick $g G
-       label H
+       label second
 
        reset branch-point # C
        pick $d D
-       merge -C $e E # E
-       merge -C $h H # H
+       merge -C $e first # E
+       merge -C $h second # H
 
        EOF
 
@@ -462,11 +462,11 @@ test_expect_success 'A root commit can be a cousin, treat it that way' '
 '
 
 test_expect_success 'labels that are object IDs are rewritten' '
-       git checkout -b third B &&
+       git checkout --detach B &&
        test_commit I &&
        third=$(git rev-parse HEAD) &&
        git checkout -b labels main &&
-       git merge --no-commit third &&
+       git merge --no-commit $third &&
        test_tick &&
        git commit -m "Merge commit '\''$third'\'' into labels" &&
        echo noop >script-from-scratch &&