t / t3430-rebase-merges.shon commit rebase --rebase-merges: avoid "empty merges" (7ccdf65)
   1#!/bin/sh
   2#
   3# Copyright (c) 2018 Johannes E. Schindelin
   4#
   5
   6test_description='git rebase -i --rebase-merges
   7
   8This test runs git rebase "interactively", retaining the branch structure by
   9recreating merge commits.
  10
  11Initial setup:
  12
  13    -- B --                   (first)
  14   /       \
  15 A - C - D - E - H            (master)
  16       \       /
  17         F - G                (second)
  18'
  19. ./test-lib.sh
  20. "$TEST_DIRECTORY"/lib-rebase.sh
  21
  22test_cmp_graph () {
  23        cat >expect &&
  24        git log --graph --boundary --format=%s "$@" >output &&
  25        sed "s/ *$//" <output >output.trimmed &&
  26        test_cmp expect output.trimmed
  27}
  28
  29test_expect_success 'setup' '
  30        write_script replace-editor.sh <<-\EOF &&
  31        mv "$1" "$(git rev-parse --git-path ORIGINAL-TODO)"
  32        cp script-from-scratch "$1"
  33        EOF
  34
  35        test_commit A &&
  36        git checkout -b first &&
  37        test_commit B &&
  38        git checkout master &&
  39        test_commit C &&
  40        test_commit D &&
  41        git merge --no-commit B &&
  42        test_tick &&
  43        git commit -m E &&
  44        git tag -m E E &&
  45        git checkout -b second C &&
  46        test_commit F &&
  47        test_commit G &&
  48        git checkout master &&
  49        git merge --no-commit G &&
  50        test_tick &&
  51        git commit -m H &&
  52        git tag -m H H
  53'
  54
  55test_expect_success 'create completely different structure' '
  56        cat >script-from-scratch <<-\EOF &&
  57        label onto
  58
  59        # onebranch
  60        pick G
  61        pick D
  62        label onebranch
  63
  64        # second
  65        reset onto
  66        pick B
  67        label second
  68
  69        reset onto
  70        merge -C H second
  71        merge onebranch # Merge the topic branch '\''onebranch'\''
  72        EOF
  73        test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
  74        test_tick &&
  75        git rebase -i -r A &&
  76        test_cmp_graph <<-\EOF
  77        *   Merge the topic branch '\''onebranch'\''
  78        |\
  79        | * D
  80        | * G
  81        * |   H
  82        |\ \
  83        | |/
  84        |/|
  85        | * B
  86        |/
  87        * A
  88        EOF
  89'
  90
  91test_expect_success 'generate correct todo list' '
  92        cat >expect <<-\EOF &&
  93        label onto
  94
  95        reset onto
  96        pick d9df450 B
  97        label E
  98
  99        reset onto
 100        pick 5dee784 C
 101        label branch-point
 102        pick ca2c861 F
 103        pick 088b00a G
 104        label H
 105
 106        reset branch-point # C
 107        pick 12bd07b D
 108        merge -C 2051b56 E # E
 109        merge -C 233d48a H # H
 110
 111        EOF
 112
 113        grep -v "^#" <.git/ORIGINAL-TODO >output &&
 114        test_cmp expect output
 115'
 116
 117test_expect_success '`reset` refuses to overwrite untracked files' '
 118        git checkout -b refuse-to-reset &&
 119        test_commit dont-overwrite-untracked &&
 120        git checkout @{-1} &&
 121        : >dont-overwrite-untracked.t &&
 122        echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch &&
 123        test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
 124        test_must_fail git rebase -r HEAD &&
 125        git rebase --abort
 126'
 127
 128test_expect_success 'failed `merge` writes patch (may be rescheduled, too)' '
 129        test_when_finished "test_might_fail git rebase --abort" &&
 130        git checkout -b conflicting-merge A &&
 131
 132        : fail because of conflicting untracked file &&
 133        >G.t &&
 134        echo "merge -C H G" >script-from-scratch &&
 135        test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
 136        test_tick &&
 137        test_must_fail git rebase -ir HEAD &&
 138        grep "^merge -C .* G$" .git/rebase-merge/done &&
 139        grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
 140        test_path_is_file .git/rebase-merge/patch &&
 141
 142        : fail because of merge conflict &&
 143        rm G.t .git/rebase-merge/patch &&
 144        git reset --hard &&
 145        test_commit conflicting-G G.t not-G conflicting-G &&
 146        test_must_fail git rebase --continue &&
 147        ! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
 148        test_path_is_file .git/rebase-merge/patch
 149'
 150
 151test_expect_success 'with a branch tip that was cherry-picked already' '
 152        git checkout -b already-upstream master &&
 153        base="$(git rev-parse --verify HEAD)" &&
 154
 155        test_commit A1 &&
 156        test_commit A2 &&
 157        git reset --hard $base &&
 158        test_commit B1 &&
 159        test_tick &&
 160        git merge -m "Merge branch A" A2 &&
 161
 162        git checkout -b upstream-with-a2 $base &&
 163        test_tick &&
 164        git cherry-pick A2 &&
 165
 166        git checkout already-upstream &&
 167        test_tick &&
 168        git rebase -i -r upstream-with-a2 &&
 169        test_cmp_graph upstream-with-a2.. <<-\EOF
 170        *   Merge branch A
 171        |\
 172        | * A1
 173        * | B1
 174        |/
 175        o A2
 176        EOF
 177'
 178
 179test_expect_success 'refs/rewritten/* is worktree-local' '
 180        git worktree add wt &&
 181        cat >wt/script-from-scratch <<-\EOF &&
 182        label xyz
 183        exec GIT_DIR=../.git git rev-parse --verify refs/rewritten/xyz >a || :
 184        exec git rev-parse --verify refs/rewritten/xyz >b
 185        EOF
 186
 187        test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
 188        git -C wt rebase -i HEAD &&
 189        test_must_be_empty wt/a &&
 190        test_cmp_rev HEAD "$(cat wt/b)"
 191'
 192
 193test_expect_success 'post-rewrite hook and fixups work for merges' '
 194        git checkout -b post-rewrite &&
 195        test_commit same1 &&
 196        git reset --hard HEAD^ &&
 197        test_commit same2 &&
 198        git merge -m "to fix up" same1 &&
 199        echo same old same old >same2.t &&
 200        test_tick &&
 201        git commit --fixup HEAD same2.t &&
 202        fixup="$(git rev-parse HEAD)" &&
 203
 204        mkdir -p .git/hooks &&
 205        test_when_finished "rm .git/hooks/post-rewrite" &&
 206        echo "cat >actual" | write_script .git/hooks/post-rewrite &&
 207
 208        test_tick &&
 209        git rebase -i --autosquash -r HEAD^^^ &&
 210        printf "%s %s\n%s %s\n%s %s\n%s %s\n" >expect $(git rev-parse \
 211                $fixup^^2 HEAD^2 \
 212                $fixup^^ HEAD^ \
 213                $fixup^ HEAD \
 214                $fixup HEAD) &&
 215        test_cmp expect actual
 216'
 217
 218test_expect_success 'refuse to merge ancestors of HEAD' '
 219        echo "merge HEAD^" >script-from-scratch &&
 220        test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
 221        before="$(git rev-parse HEAD)" &&
 222        git rebase -i HEAD &&
 223        test_cmp_rev HEAD $before
 224'
 225
 226test_done