struct commit *base, *replayed_base;
struct tree *pickme_tree, *base_tree, *replayed_base_tree;
- base = pickme->parents->item;
- replayed_base = mapped_commit(replayed_commits, base, onto);
+ if (pickme->parents) {
+ base = pickme->parents->item;
+ base_tree = repo_get_commit_tree(repo, base);
+ } else {
+ base = NULL;
+ base_tree = lookup_tree(repo, repo->hash_algo->empty_tree);
+ }
+ replayed_base = mapped_commit(replayed_commits, base, onto);
replayed_base_tree = repo_get_commit_tree(repo, replayed_base);
pickme_tree = repo_get_commit_tree(repo, pickme);
- base_tree = repo_get_commit_tree(repo, base);
- merge_opt->branch1 = short_commit_name(repo, replayed_base);
- merge_opt->branch2 = short_commit_name(repo, pickme);
- if (pickme->parents)
- merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2);
- else
- merge_opt->ancestor = xstrdup("empty tree");
-
- merge_incore_nonrecursive(merge_opt,
- base_tree,
- replayed_base_tree,
- pickme_tree,
- result);
-
- free((char*)merge_opt->ancestor);
+ if (mode == REPLAY_MODE_PICK) {
+ /* Cherry-pick: normal order */
+ merge_opt->branch1 = short_commit_name(repo, replayed_base);
+ merge_opt->branch2 = short_commit_name(repo, pickme);
- merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2);
++ if (pickme->parents)
++ merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2);
++ else
++ merge_opt->ancestor = xstrdup("empty tree");
+
+ merge_incore_nonrecursive(merge_opt,
+ base_tree,
+ replayed_base_tree,
+ pickme_tree,
+ result);
+
+ free((char *)merge_opt->ancestor);
+ } else if (mode == REPLAY_MODE_REVERT) {
+ /* Revert: swap base and pickme to reverse the diff */
+ const char *pickme_name = short_commit_name(repo, pickme);
+ merge_opt->branch1 = short_commit_name(repo, replayed_base);
+ merge_opt->branch2 = xstrfmt("parent of %s", pickme_name);
+ merge_opt->ancestor = pickme_name;
+
+ merge_incore_nonrecursive(merge_opt,
+ pickme_tree,
+ replayed_base_tree,
+ base_tree,
+ result);
+
+ free((char *)merge_opt->branch2);
+ } else {
+ BUG("unexpected replay mode %d", mode);
+ }
merge_opt->ancestor = NULL;
+ merge_opt->branch2 = NULL;
if (!result->clean)
return NULL;
/* Drop commits that become empty */
int ret;
advance = xstrdup_or_null(opts->advance);
+ revert = xstrdup_or_null(opts->revert);
+ if (revert)
+ mode = REPLAY_MODE_REVERT;
set_up_replay_mode(revs->repo, &revs->cmdline, opts->onto,
- &detached_head, &advance, &onto, &update_refs);
+ &detached_head, &advance, &revert, &onto, &update_refs);
- /* FIXME: Should allow replaying commits with the first as a root commit */
-
if (prepare_revision_walk(revs) < 0) {
ret = error(_("error preparing revisions"));
goto out;