>From the user's point of view, it seems natural to think that
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 <martinv...@gmail.com>

---

The plan is to use this for fixing "git rebase --root" as discussed in
http://thread.gmane.org/gmane.comp.version-control.git/205796

Is there a better way of creating an unborn branch than what I do in
the test cases?

 sequencer.c                   | 19 +++++++++++--------
 t/t3501-revert-cherry-pick.sh |  9 +++++++++
 t/t3506-cherry-pick-ff.sh     |  8 ++++++++
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 2260490..1ac1ceb 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -186,14 +186,15 @@ static int error_dirty_index(struct replay_opts *opts)
        return -1;
 }
 
-static int fast_forward_to(const unsigned char *to, const unsigned char *from)
+static int fast_forward_to(const unsigned char *to, const unsigned char *from,
+                          int unborn)
 {
        struct ref_lock *ref_lock;
 
        read_cache();
        if (checkout_fast_forward(from, to, 1))
                exit(1); /* the callee should have complained already */
-       ref_lock = lock_any_ref_for_update("HEAD", from, 0);
+       ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from, 
0);
        return write_ref_sha1(ref_lock, to, "cherry-pick");
 }
 
@@ -390,7 +391,7 @@ static int do_pick_commit(struct commit *commit, struct 
replay_opts *opts)
        struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
        char *defmsg = NULL;
        struct strbuf msgbuf = STRBUF_INIT;
-       int res;
+       int res, unborn = 0;
 
        if (opts->no_commit) {
                /*
@@ -402,9 +403,10 @@ static int do_pick_commit(struct commit *commit, struct 
replay_opts *opts)
                if (write_cache_as_tree(head, 0, NULL))
                        die (_("Your index file is unmerged."));
        } else {
-               if (get_sha1("HEAD", head))
-                       return error(_("You do not have a valid HEAD"));
-               if (index_differs_from("HEAD", 0))
+               unborn = get_sha1("HEAD", head);
+               if (unborn)
+                       hashcpy(head, EMPTY_TREE_SHA1_BIN);
+               if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 
0))
                        return error_dirty_index(opts);
        }
        discard_cache();
@@ -435,8 +437,9 @@ static int do_pick_commit(struct commit *commit, struct 
replay_opts *opts)
        else
                parent = commit->parents->item;
 
-       if (opts->allow_ff && parent && !hashcmp(parent->object.sha1, head))
-               return fast_forward_to(commit->object.sha1, head);
+       if (opts->allow_ff &&
+           (parent && !hashcmp(parent->object.sha1, head) || !parent && 
unborn))
+            return fast_forward_to(commit->object.sha1, head, unborn);
 
        if (parent && parse_commit(parent) < 0)
                /* TRANSLATORS: The first %s will be "revert" or
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 34c86e5..6f489e2 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -100,4 +100,13 @@ test_expect_success 'revert forbidden on dirty working 
tree' '
 
 '
 
+test_expect_success 'chery-pick on unborn branch' '
+       git checkout --orphan unborn &&
+       git rm --cached -r . &&
+       rm -rf * &&
+       git cherry-pick initial &&
+       git diff --quiet initial &&
+       ! test_cmp_rev initial HEAD
+'
+
 test_done
diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index 51ca391..373aad6 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -105,4 +105,12 @@ test_expect_success 'cherry pick a root commit with --ff' '
        test "$(git rev-parse --verify HEAD)" = 
"1df192cd8bc58a2b275d842cede4d221ad9000d1"
 '
 
+test_expect_success 'chery-pick --ff on unborn branch' '
+       git checkout --orphan unborn &&
+       git rm --cached -r . &&
+       rm -rf * &&
+       git cherry-pick --ff first &&
+       test_cmp_rev first HEAD
+'
+
 test_done
-- 
1.8.0.1.240.ge8a1f5a

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to