t / t3430-rebase-merges.shon commit Merge branch 'tb/test-apfs-utf8-normalization' (71cdbb3)
   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 'do not rebase cousins unless asked for' '
 180        git checkout -b cousins master &&
 181        before="$(git rev-parse --verify HEAD)" &&
 182        test_tick &&
 183        git rebase -r HEAD^ &&
 184        test_cmp_rev HEAD $before &&
 185        test_tick &&
 186        git rebase --rebase-merges=rebase-cousins HEAD^ &&
 187        test_cmp_graph HEAD^.. <<-\EOF
 188        *   Merge the topic branch '\''onebranch'\''
 189        |\
 190        | * D
 191        | * G
 192        |/
 193        o H
 194        EOF
 195'
 196
 197test_expect_success 'refs/rewritten/* is worktree-local' '
 198        git worktree add wt &&
 199        cat >wt/script-from-scratch <<-\EOF &&
 200        label xyz
 201        exec GIT_DIR=../.git git rev-parse --verify refs/rewritten/xyz >a || :
 202        exec git rev-parse --verify refs/rewritten/xyz >b
 203        EOF
 204
 205        test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
 206        git -C wt rebase -i HEAD &&
 207        test_must_be_empty wt/a &&
 208        test_cmp_rev HEAD "$(cat wt/b)"
 209'
 210
 211test_expect_success 'post-rewrite hook and fixups work for merges' '
 212        git checkout -b post-rewrite &&
 213        test_commit same1 &&
 214        git reset --hard HEAD^ &&
 215        test_commit same2 &&
 216        git merge -m "to fix up" same1 &&
 217        echo same old same old >same2.t &&
 218        test_tick &&
 219        git commit --fixup HEAD same2.t &&
 220        fixup="$(git rev-parse HEAD)" &&
 221
 222        mkdir -p .git/hooks &&
 223        test_when_finished "rm .git/hooks/post-rewrite" &&
 224        echo "cat >actual" | write_script .git/hooks/post-rewrite &&
 225
 226        test_tick &&
 227        git rebase -i --autosquash -r HEAD^^^ &&
 228        printf "%s %s\n%s %s\n%s %s\n%s %s\n" >expect $(git rev-parse \
 229                $fixup^^2 HEAD^2 \
 230                $fixup^^ HEAD^ \
 231                $fixup^ HEAD \
 232                $fixup HEAD) &&
 233        test_cmp expect actual
 234'
 235
 236test_expect_success 'refuse to merge ancestors of HEAD' '
 237        echo "merge HEAD^" >script-from-scratch &&
 238        test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
 239        before="$(git rev-parse HEAD)" &&
 240        git rebase -i HEAD &&
 241        test_cmp_rev HEAD $before
 242'
 243
 244test_done