Skip to content

Commit 6a37cee

Browse files
committed
Merge branch 'mz/pick-unborn'
Allow "git cherry-pick $commit" even when you do not have any history behind HEAD yet. * mz/pick-unborn: learn to pick/revert into unborn branch tests: move test_cmp_rev to test-lib-functions
2 parents 377bf8d + 334ae39 commit 6a37cee

10 files changed

+44
-48
lines changed

sequencer.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,15 @@ static int error_dirty_index(struct replay_opts *opts)
186186
return -1;
187187
}
188188

189-
static int fast_forward_to(const unsigned char *to, const unsigned char *from)
189+
static int fast_forward_to(const unsigned char *to, const unsigned char *from,
190+
int unborn)
190191
{
191192
struct ref_lock *ref_lock;
192193

193194
read_cache();
194195
if (checkout_fast_forward(from, to, 1))
195196
exit(1); /* the callee should have complained already */
196-
ref_lock = lock_any_ref_for_update("HEAD", from, 0);
197+
ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from, 0);
197198
return write_ref_sha1(ref_lock, to, "cherry-pick");
198199
}
199200

@@ -390,7 +391,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
390391
struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
391392
char *defmsg = NULL;
392393
struct strbuf msgbuf = STRBUF_INIT;
393-
int res;
394+
int res, unborn = 0;
394395

395396
if (opts->no_commit) {
396397
/*
@@ -402,9 +403,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
402403
if (write_cache_as_tree(head, 0, NULL))
403404
die (_("Your index file is unmerged."));
404405
} else {
405-
if (get_sha1("HEAD", head))
406-
return error(_("You do not have a valid HEAD"));
407-
if (index_differs_from("HEAD", 0))
406+
unborn = get_sha1("HEAD", head);
407+
if (unborn)
408+
hashcpy(head, EMPTY_TREE_SHA1_BIN);
409+
if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0))
408410
return error_dirty_index(opts);
409411
}
410412
discard_cache();
@@ -435,8 +437,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
435437
else
436438
parent = commit->parents->item;
437439

438-
if (opts->allow_ff && parent && !hashcmp(parent->object.sha1, head))
439-
return fast_forward_to(commit->object.sha1, head);
440+
if (opts->allow_ff &&
441+
((parent && !hashcmp(parent->object.sha1, head)) ||
442+
(!parent && unborn)))
443+
return fast_forward_to(commit->object.sha1, head, unborn);
440444

441445
if (parent && parse_commit(parent) < 0)
442446
/* TRANSLATORS: The first %s will be "revert" or

t/t1505-rev-parse-last.sh

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,24 @@ test_expect_success 'setup' '
3232
#
3333
# and 'side' should be the last branch
3434

35-
test_rev_equivalent () {
36-
37-
git rev-parse "$1" > expect &&
38-
git rev-parse "$2" > output &&
39-
test_cmp expect output
40-
41-
}
42-
4335
test_expect_success '@{-1} works' '
44-
test_rev_equivalent side @{-1}
36+
test_cmp_rev side @{-1}
4537
'
4638

4739
test_expect_success '@{-1}~2 works' '
48-
test_rev_equivalent side~2 @{-1}~2
40+
test_cmp_rev side~2 @{-1}~2
4941
'
5042

5143
test_expect_success '@{-1}^2 works' '
52-
test_rev_equivalent side^2 @{-1}^2
44+
test_cmp_rev side^2 @{-1}^2
5345
'
5446

5547
test_expect_success '@{-1}@{1} works' '
56-
test_rev_equivalent side@{1} @{-1}@{1}
48+
test_cmp_rev side@{1} @{-1}@{1}
5749
'
5850

5951
test_expect_success '@{-2} works' '
60-
test_rev_equivalent master @{-2}
52+
test_cmp_rev master @{-2}
6153
'
6254

6355
test_expect_success '@{-3} fails' '

t/t3404-rebase-interactive.sh

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ Initial setup:
2929

3030
. "$TEST_DIRECTORY"/lib-rebase.sh
3131

32-
test_cmp_rev () {
33-
git rev-parse --verify "$1" >expect.rev &&
34-
git rev-parse --verify "$2" >actual.rev &&
35-
test_cmp expect.rev actual.rev
36-
}
37-
3832
set_fake_editor
3933

4034
# WARNING: Modifications to the initial repository can change the SHA ID used

t/t3501-revert-cherry-pick.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,13 @@ test_expect_success 'revert forbidden on dirty working tree' '
100100
101101
'
102102

103+
test_expect_success 'chery-pick on unborn branch' '
104+
git checkout --orphan unborn &&
105+
git rm --cached -r . &&
106+
rm -rf * &&
107+
git cherry-pick initial &&
108+
git diff --quiet initial &&
109+
! test_cmp_rev initial HEAD
110+
'
111+
103112
test_done

t/t3506-cherry-pick-ff.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,12 @@ test_expect_success 'cherry pick a root commit with --ff' '
105105
test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1"
106106
'
107107

108+
test_expect_success 'chery-pick --ff on unborn branch' '
109+
git checkout --orphan unborn &&
110+
git rm --cached -r . &&
111+
rm -rf * &&
112+
git cherry-pick --ff first &&
113+
test_cmp_rev first HEAD
114+
'
115+
108116
test_done

t/t3507-cherry-pick-conflict.sh

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ test_description='test cherry-pick and revert with conflicts
1111

1212
. ./test-lib.sh
1313

14-
test_cmp_rev () {
15-
git rev-parse --verify "$1" >expect.rev &&
16-
git rev-parse --verify "$2" >actual.rev &&
17-
test_cmp expect.rev actual.rev
18-
}
19-
2014
pristine_detach () {
2115
git checkout -f "$1^0" &&
2216
git read-tree -u --reset HEAD &&

t/t3508-cherry-pick-many-commits.sh

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,11 @@ test_description='test cherry-picking many commits'
55
. ./test-lib.sh
66

77
check_head_differs_from() {
8-
head=$(git rev-parse --verify HEAD) &&
9-
arg=$(git rev-parse --verify "$1") &&
10-
test "$head" != "$arg"
8+
! test_cmp_rev HEAD "$1"
119
}
1210

1311
check_head_equals() {
14-
head=$(git rev-parse --verify HEAD) &&
15-
arg=$(git rev-parse --verify "$1") &&
16-
test "$head" = "$arg"
12+
test_cmp_rev HEAD "$1"
1713
}
1814

1915
test_expect_success setup '

t/t3510-cherry-pick-sequence.sh

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ pristine_detach () {
2424
git clean -d -f -f -q -x
2525
}
2626

27-
test_cmp_rev () {
28-
git rev-parse --verify "$1" >expect.rev &&
29-
git rev-parse --verify "$2" >actual.rev &&
30-
test_cmp expect.rev actual.rev
31-
}
32-
3327
test_expect_success setup '
3428
git config advice.detachedhead false &&
3529
echo unrelated >unrelated &&

t/t6030-bisect-porcelain.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -676,9 +676,7 @@ test_expect_success 'bisect fails if tree is broken on trial commit' '
676676
check_same()
677677
{
678678
echo "Checking $1 is the same as $2" &&
679-
git rev-parse "$1" > expected.same &&
680-
git rev-parse "$2" > expected.actual &&
681-
test_cmp expected.same expected.actual
679+
test_cmp_rev "$1" "$2"
682680
}
683681

684682
test_expect_success 'bisect: --no-checkout - start commit bad' '

t/test-lib-functions.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,13 @@ test_cmp() {
602602
$GIT_TEST_CMP "$@"
603603
}
604604

605+
# Tests that its two parameters refer to the same revision
606+
test_cmp_rev () {
607+
git rev-parse --verify "$1" >expect.rev &&
608+
git rev-parse --verify "$2" >actual.rev &&
609+
test_cmp expect.rev actual.rev
610+
}
611+
605612
# Print a sequence of numbers or letters in increasing order. This is
606613
# similar to GNU seq(1), but the latter might not be available
607614
# everywhere (and does not do letters). It may be used like:

0 commit comments

Comments
 (0)