Git 2.22.4
[git] / t / t2018-checkout-branch.sh
1 #!/bin/sh
2
3 test_description='checkout '
4
5 . ./test-lib.sh
6
7 # Arguments: <branch> <sha> [<checkout options>]
8 #
9 # Runs "git checkout" to switch to <branch>, testing that
10 #
11 #   1) we are on the specified branch, <branch>;
12 #   2) HEAD is <sha>; if <sha> is not specified, the old HEAD is used.
13 #
14 # If <checkout options> is not specified, "git checkout" is run with -b.
15 do_checkout() {
16         exp_branch=$1 &&
17         exp_ref="refs/heads/$exp_branch" &&
18
19         # if <sha> is not specified, use HEAD.
20         exp_sha=${2:-$(git rev-parse --verify HEAD)} &&
21
22         # default options for git checkout: -b
23         if [ -z "$3" ]; then
24                 opts="-b"
25         else
26                 opts="$3"
27         fi
28
29         git checkout $opts $exp_branch $exp_sha &&
30
31         test $exp_ref = $(git rev-parse --symbolic-full-name HEAD) &&
32         test $exp_sha = $(git rev-parse --verify HEAD)
33 }
34
35 test_dirty_unmergeable() {
36         ! git diff --exit-code >/dev/null
37 }
38
39 setup_dirty_unmergeable() {
40         echo >>file1 change2
41 }
42
43 test_dirty_mergeable() {
44         ! git diff --cached --exit-code >/dev/null
45 }
46
47 setup_dirty_mergeable() {
48         echo >file2 file2 &&
49         git add file2
50 }
51
52 test_expect_success 'setup' '
53         test_commit initial file1 &&
54         HEAD1=$(git rev-parse --verify HEAD) &&
55
56         test_commit change1 file1 &&
57         HEAD2=$(git rev-parse --verify HEAD) &&
58
59         git branch -m branch1
60 '
61
62 test_expect_success 'checkout -b to a new branch, set to HEAD' '
63         test_when_finished "
64                 git checkout branch1 &&
65                 test_might_fail git branch -D branch2" &&
66         do_checkout branch2
67 '
68
69 test_expect_success 'checkout -b to a merge base' '
70         test_when_finished "
71                 git checkout branch1 &&
72                 test_might_fail git branch -D branch2" &&
73         git checkout -b branch2 branch1...
74 '
75
76 test_expect_success 'checkout -b to a new branch, set to an explicit ref' '
77         test_when_finished "
78                 git checkout branch1 &&
79                 test_might_fail git branch -D branch2" &&
80         do_checkout branch2 $HEAD1
81 '
82
83 test_expect_success 'checkout -b to a new branch with unmergeable changes fails' '
84         setup_dirty_unmergeable &&
85         test_must_fail do_checkout branch2 $HEAD1 &&
86         test_dirty_unmergeable
87 '
88
89 test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' '
90         test_when_finished "
91                 git checkout branch1 &&
92                 test_might_fail git branch -D branch2" &&
93
94         # still dirty and on branch1
95         do_checkout branch2 $HEAD1 "-f -b" &&
96         test_must_fail test_dirty_unmergeable
97 '
98
99 test_expect_success 'checkout -b to a new branch preserves mergeable changes' '
100         test_when_finished "
101                 git reset --hard &&
102                 git checkout branch1 &&
103                 test_might_fail git branch -D branch2" &&
104
105         setup_dirty_mergeable &&
106         do_checkout branch2 $HEAD1 &&
107         test_dirty_mergeable
108 '
109
110 test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' '
111         test_when_finished git reset --hard HEAD &&
112         setup_dirty_mergeable &&
113         do_checkout branch2 $HEAD1 "-f -b" &&
114         test_must_fail test_dirty_mergeable
115 '
116
117 test_expect_success 'checkout -b to an existing branch fails' '
118         test_when_finished git reset --hard HEAD &&
119         test_must_fail do_checkout branch2 $HEAD2
120 '
121
122 test_expect_success 'checkout -b to @{-1} fails with the right branch name' '
123         git checkout branch1 &&
124         git checkout branch2 &&
125         echo  >expect "fatal: A branch named '\''branch1'\'' already exists." &&
126         test_must_fail git checkout -b @{-1} 2>actual &&
127         test_i18ncmp expect actual
128 '
129
130 test_expect_success 'checkout -B to an existing branch resets branch to HEAD' '
131         git checkout branch1 &&
132
133         do_checkout branch2 "" -B
134 '
135
136 test_expect_success 'checkout -B to a merge base' '
137         git checkout branch1 &&
138
139         git checkout -B branch2 branch1...
140 '
141
142 test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' '
143         git checkout $(git rev-parse --verify HEAD) &&
144
145         do_checkout branch2 "" -B
146 '
147
148 test_expect_success 'checkout -B to an existing branch with an explicit ref resets branch to that ref' '
149         git checkout branch1 &&
150
151         do_checkout branch2 $HEAD1 -B
152 '
153
154 test_expect_success 'checkout -B to an existing branch with unmergeable changes fails' '
155         git checkout branch1 &&
156
157         setup_dirty_unmergeable &&
158         test_must_fail do_checkout branch2 $HEAD1 -B &&
159         test_dirty_unmergeable
160 '
161
162 test_expect_success 'checkout -f -B to an existing branch with unmergeable changes discards changes' '
163         # still dirty and on branch1
164         do_checkout branch2 $HEAD1 "-f -B" &&
165         test_must_fail test_dirty_unmergeable
166 '
167
168 test_expect_success 'checkout -B to an existing branch preserves mergeable changes' '
169         test_when_finished git reset --hard &&
170         git checkout branch1 &&
171
172         setup_dirty_mergeable &&
173         do_checkout branch2 $HEAD1 -B &&
174         test_dirty_mergeable
175 '
176
177 test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' '
178         git checkout branch1 &&
179
180         setup_dirty_mergeable &&
181         do_checkout branch2 $HEAD1 "-f -B" &&
182         test_must_fail test_dirty_mergeable
183 '
184
185 test_expect_success 'checkout -b <describe>' '
186         git tag -f -m "First commit" initial initial &&
187         git checkout -f change1 &&
188         name=$(git describe) &&
189         git checkout -b $name &&
190         git diff --exit-code change1 &&
191         echo "refs/heads/$name" >expect &&
192         git symbolic-ref HEAD >actual &&
193         test_cmp expect actual
194 '
195
196 test_expect_success 'checkout -B to the current branch works' '
197         git checkout branch1 &&
198         git checkout -B branch1-scratch &&
199
200         setup_dirty_mergeable &&
201         git checkout -B branch1-scratch initial &&
202         test_dirty_mergeable
203 '
204
205 test_expect_success 'checkout -b after clone --no-checkout does a checkout of HEAD' '
206         git init src &&
207         test_commit -C src a &&
208         rev="$(git -C src rev-parse HEAD)" &&
209         git clone --no-checkout src dest &&
210         git -C dest checkout "$rev" -b branch &&
211         test_path_is_file dest/a.t
212 '
213
214 test_done