Skip to content

Commit 334ae39

Browse files
martinvonzgitster
authored andcommitted
learn to pick/revert into unborn branch
cherry-picking into an unborn branch should work, so make it work, with or without --ff. Cherry-picking anything other than a commit that only adds files, will naturally result in conflicts. Similarly, revert also works, but will result in conflicts unless the specified revision only deletes files. Signed-off-by: Martin von Zweigbergk <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5d77298 commit 334ae39

File tree

3 files changed

+29
-8
lines changed

3 files changed

+29
-8
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/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

0 commit comments

Comments
 (0)