Skip to content

Commit

Permalink
Allow cherry-picking root commits
Browse files Browse the repository at this point in the history
A root commit couldn't be cherry-picked.  But its semantics can be
defined as simply merging two trees by overlaying disjoint parts
and merging overlapping files without any common ancestor.  You
should be able to rebase originally independent branches on top of
another branch by using this.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Johannes Schindelin authored and Junio C Hamano committed Jul 7, 2008
1 parent 44701c6 commit f95ebf7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 10 deletions.
26 changes: 16 additions & 10 deletions builtin-revert.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ static int merge_recursive(const char *base_sha1,
{
char buffer[256];
const char *argv[6];
int i = 0;

sprintf(buffer, "GITHEAD_%s", head_sha1);
setenv(buffer, head_name, 1);
Expand All @@ -218,12 +219,13 @@ static int merge_recursive(const char *base_sha1,
* and $prev on top of us (when reverting), or the change between
* $prev and $commit on top of us (when cherry-picking or replaying).
*/
argv[0] = "merge-recursive";
argv[1] = base_sha1;
argv[2] = "--";
argv[3] = head_sha1;
argv[4] = next_sha1;
argv[5] = NULL;
argv[i++] = "merge-recursive";
if (base_sha1)
argv[i++] = base_sha1;
argv[i++] = "--";
argv[i++] = head_sha1;
argv[i++] = next_sha1;
argv[i++] = NULL;

return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
}
Expand Down Expand Up @@ -297,9 +299,12 @@ static int revert_or_cherry_pick(int argc, const char **argv)
discard_cache();
}

if (!commit->parents)
die ("Cannot %s a root commit", me);
if (commit->parents->next) {
if (!commit->parents) {
if (action == REVERT)
die ("Cannot revert a root commit");
parent = NULL;
}
else if (commit->parents->next) {
/* Reverting or cherry-picking a merge commit */
int cnt;
struct commit_list *p;
Expand Down Expand Up @@ -368,7 +373,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
}
}

if (merge_recursive(sha1_to_hex(base->object.sha1),
if (merge_recursive(base == NULL ?
NULL : sha1_to_hex(base->object.sha1),
sha1_to_hex(head), "HEAD",
sha1_to_hex(next->object.sha1), oneline) ||
write_cache_as_tree(head, 0, NULL)) {
Expand Down
30 changes: 30 additions & 0 deletions t/t3503-cherry-pick-root.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh

test_description='test cherry-picking a root commit'

. ./test-lib.sh

test_expect_success setup '
echo first > file1 &&
git add file1 &&
test_tick &&
git commit -m "first" &&
git symbolic-ref HEAD refs/heads/second &&
rm .git/index file1 &&
echo second > file2 &&
git add file2 &&
test_tick &&
git commit -m "second"
'

test_expect_success 'cherry-pick a root commit' '
git cherry-pick master &&
test first = $(cat file1)
'

test_done

0 comments on commit f95ebf7

Please sign in to comment.