зеркало из https://github.com/microsoft/git.git
Merge branch 'nh/empty-rebase'
* nh/empty-rebase: cherry-pick: regression fix for empty commits
This commit is contained in:
Коммит
264d5a717b
73
sequencer.c
73
sequencer.c
|
@ -291,7 +291,8 @@ static int is_index_unchanged(void)
|
||||||
* If we are revert, or if our cherry-pick results in a hand merge,
|
* If we are revert, or if our cherry-pick results in a hand merge,
|
||||||
* we had better say that the current user is responsible for that.
|
* we had better say that the current user is responsible for that.
|
||||||
*/
|
*/
|
||||||
static int run_git_commit(const char *defmsg, struct replay_opts *opts)
|
static int run_git_commit(const char *defmsg, struct replay_opts *opts,
|
||||||
|
int allow_empty)
|
||||||
{
|
{
|
||||||
struct argv_array array;
|
struct argv_array array;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -307,7 +308,7 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts)
|
||||||
argv_array_push(&array, defmsg);
|
argv_array_push(&array, defmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->allow_empty)
|
if (allow_empty)
|
||||||
argv_array_push(&array, "--allow-empty");
|
argv_array_push(&array, "--allow-empty");
|
||||||
|
|
||||||
rc = run_command_v_opt(array.argv, RUN_GIT_CMD);
|
rc = run_command_v_opt(array.argv, RUN_GIT_CMD);
|
||||||
|
@ -335,6 +336,44 @@ static int is_original_commit_empty(struct commit *commit)
|
||||||
return !hashcmp(ptree_sha1, commit->tree->object.sha1);
|
return !hashcmp(ptree_sha1, commit->tree->object.sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do we run "git commit" with "--allow-empty"?
|
||||||
|
*/
|
||||||
|
static int allow_empty(struct replay_opts *opts, struct commit *commit)
|
||||||
|
{
|
||||||
|
int index_unchanged, empty_commit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Three cases:
|
||||||
|
*
|
||||||
|
* (1) we do not allow empty at all and error out.
|
||||||
|
*
|
||||||
|
* (2) we allow ones that were initially empty, but
|
||||||
|
* forbid the ones that become empty;
|
||||||
|
*
|
||||||
|
* (3) we allow both.
|
||||||
|
*/
|
||||||
|
if (!opts->allow_empty)
|
||||||
|
return 0; /* let "git commit" barf as necessary */
|
||||||
|
|
||||||
|
index_unchanged = is_index_unchanged();
|
||||||
|
if (index_unchanged < 0)
|
||||||
|
return index_unchanged;
|
||||||
|
if (!index_unchanged)
|
||||||
|
return 0; /* we do not have to say --allow-empty */
|
||||||
|
|
||||||
|
if (opts->keep_redundant_commits)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
empty_commit = is_original_commit_empty(commit);
|
||||||
|
if (empty_commit < 0)
|
||||||
|
return empty_commit;
|
||||||
|
if (!empty_commit)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||||
{
|
{
|
||||||
unsigned char head[20];
|
unsigned char head[20];
|
||||||
|
@ -344,8 +383,6 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||||
char *defmsg = NULL;
|
char *defmsg = NULL;
|
||||||
struct strbuf msgbuf = STRBUF_INIT;
|
struct strbuf msgbuf = STRBUF_INIT;
|
||||||
int res;
|
int res;
|
||||||
int empty_commit;
|
|
||||||
int index_unchanged;
|
|
||||||
|
|
||||||
if (opts->no_commit) {
|
if (opts->no_commit) {
|
||||||
/*
|
/*
|
||||||
|
@ -471,10 +508,6 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||||
free_commit_list(remotes);
|
free_commit_list(remotes);
|
||||||
}
|
}
|
||||||
|
|
||||||
empty_commit = is_original_commit_empty(commit);
|
|
||||||
if (empty_commit < 0)
|
|
||||||
return empty_commit;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the merge was clean or if it failed due to conflict, we write
|
* If the merge was clean or if it failed due to conflict, we write
|
||||||
* CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
|
* CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
|
||||||
|
@ -495,27 +528,11 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
||||||
print_advice(res == 1, opts);
|
print_advice(res == 1, opts);
|
||||||
rerere(opts->allow_rerere_auto);
|
rerere(opts->allow_rerere_auto);
|
||||||
} else {
|
} else {
|
||||||
index_unchanged = is_index_unchanged();
|
int allow = allow_empty(opts, commit);
|
||||||
/*
|
if (allow < 0)
|
||||||
* If index_unchanged is less than 0, that indicates we either
|
return allow;
|
||||||
* couldn't parse HEAD or the index, so error out here.
|
|
||||||
*/
|
|
||||||
if (index_unchanged < 0)
|
|
||||||
return index_unchanged;
|
|
||||||
|
|
||||||
if (!empty_commit && !opts->keep_redundant_commits && index_unchanged)
|
|
||||||
/*
|
|
||||||
* The head tree and the index match
|
|
||||||
* meaning the commit is empty. Since it wasn't created
|
|
||||||
* empty (based on the previous test), we can conclude
|
|
||||||
* the commit has been made redundant. Since we don't
|
|
||||||
* want to keep redundant commits, we can just return
|
|
||||||
* here, skipping this commit
|
|
||||||
*/
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!opts->no_commit)
|
if (!opts->no_commit)
|
||||||
res = run_git_commit(defmsg, opts);
|
res = run_git_commit(defmsg, opts, allow);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_message(&msg);
|
free_message(&msg);
|
||||||
|
|
|
@ -71,4 +71,34 @@ test_expect_success 'cherry pick with --keep-redundant-commits' '
|
||||||
git cherry-pick --keep-redundant-commits HEAD^
|
git cherry-pick --keep-redundant-commits HEAD^
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cherry-pick a commit that becomes no-op (prep)' '
|
||||||
|
git checkout master &&
|
||||||
|
git branch fork &&
|
||||||
|
echo foo >file2 &&
|
||||||
|
git add file2 &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "add file2 on master" &&
|
||||||
|
|
||||||
|
git checkout fork &&
|
||||||
|
echo foo >file2 &&
|
||||||
|
git add file2 &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "add file2 on the side"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cherry-pick a no-op without --keep-redundant' '
|
||||||
|
git reset --hard &&
|
||||||
|
git checkout fork^0 &&
|
||||||
|
test_must_fail git cherry-pick master
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'cherry-pick a no-op with --keep-redundant' '
|
||||||
|
git reset --hard &&
|
||||||
|
git checkout fork^0 &&
|
||||||
|
git cherry-pick --keep-redundant-commits master &&
|
||||||
|
git show -s --format='%s' >actual &&
|
||||||
|
echo "add file2 on master" >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Загрузка…
Ссылка в новой задаче