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 <martinvonz@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Martin von Zweigbergk committed Dec 21, 2012 at 11:10 UTC 334ae397452170dacfcd8e69e4a41f6a64f54eec
3 files changed +29 -8
sequencer.c
+12 -8
@@ -186,14 +186,15 @@ static int error_dirty_index(struct replay_opts *opts)
186 return -1;
187 }
188
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)
191 {
192 struct ref_lock *ref_lock;
193
194 read_cache();
195 if (checkout_fast_forward(from, to, 1))
196 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);
198 return write_ref_sha1(ref_lock, to, "cherry-pick");
199 }
200
@@ -390,7 +391,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
391 struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
392 char *defmsg = NULL;
393 struct strbuf msgbuf = STRBUF_INIT;
393 - int res;
394 + int res, unborn = 0;
395
396 if (opts->no_commit) {
397 /*
@@ -402,9 +403,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
403 if (write_cache_as_tree(head, 0, NULL))
404 die (_("Your index file is unmerged."));
405 } 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))
410 return error_dirty_index(opts);
411 }
412 discard_cache();
@@ -435,8 +437,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
437 else
438 parent = commit->parents->item;
439
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);
444
445 if (parent && parse_commit(parent) < 0)
446 /* TRANSLATORS: The first %s will be "revert" or
t/t3501-revert-cherry-pick.sh
+9
@@ -100,4 +100,13 @@ test_expect_success 'revert forbidden on dirty working tree' '
100
101 '
102
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 +
112 test_done
t/t3506-cherry-pick-ff.sh
+8
@@ -105,4 +105,12 @@ test_expect_success 'cherry pick a root commit with --ff' '
105 test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1"
106 '
107
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 +
116 test_done