Merge branch 'en/merge-restore-to-pristine'
When "git merge" finds that it cannot perform a merge, it should restore the working tree to the state before the command was initiated, but in some corner cases it didn't. * en/merge-restore-to-pristine: merge: do not exit restore_state() prematurely merge: ensure we can actually restore pre-merge state merge: make restore_state() restore staged state too merge: fix save_state() to work when there are stat-dirty files merge: do not abort early if one strategy fails to handle the merge merge: abort if index does not match HEAD for trivial merges merge-resolve: abort if index does not match HEAD merge-ort-wrappers: make printed message match the one from recursive
This commit is contained in:
@ -313,8 +313,16 @@ static int save_state(struct object_id *stash)
|
||||
int len;
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
struct strbuf buffer = STRBUF_INIT;
|
||||
struct lock_file lock_file = LOCK_INIT;
|
||||
int fd;
|
||||
int rc = -1;
|
||||
|
||||
fd = repo_hold_locked_index(the_repository, &lock_file, 0);
|
||||
refresh_cache(REFRESH_QUIET);
|
||||
if (0 <= fd)
|
||||
repo_update_index_if_able(the_repository, &lock_file);
|
||||
rollback_lock_file(&lock_file);
|
||||
|
||||
strvec_pushl(&cp.args, "stash", "create", NULL);
|
||||
cp.out = -1;
|
||||
cp.git_cmd = 1;
|
||||
@ -375,22 +383,26 @@ static void reset_hard(const struct object_id *oid, int verbose)
|
||||
static void restore_state(const struct object_id *head,
|
||||
const struct object_id *stash)
|
||||
{
|
||||
const char *args[] = { "stash", "apply", NULL, NULL };
|
||||
|
||||
if (is_null_oid(stash))
|
||||
return;
|
||||
struct strvec args = STRVEC_INIT;
|
||||
|
||||
reset_hard(head, 1);
|
||||
|
||||
args[2] = oid_to_hex(stash);
|
||||
if (is_null_oid(stash))
|
||||
goto refresh_cache;
|
||||
|
||||
strvec_pushl(&args, "stash", "apply", "--index", "--quiet", NULL);
|
||||
strvec_push(&args, oid_to_hex(stash));
|
||||
|
||||
/*
|
||||
* It is OK to ignore error here, for example when there was
|
||||
* nothing to restore.
|
||||
*/
|
||||
run_command_v_opt(args, RUN_GIT_CMD);
|
||||
run_command_v_opt(args.v, RUN_GIT_CMD);
|
||||
strvec_clear(&args);
|
||||
|
||||
refresh_cache(REFRESH_QUIET);
|
||||
refresh_cache:
|
||||
if (discard_cache() < 0 || read_cache() < 0)
|
||||
die(_("could not read index"));
|
||||
}
|
||||
|
||||
/* This is called when no merge was necessary. */
|
||||
@ -754,8 +766,10 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
||||
else
|
||||
clean = merge_recursive(&o, head, remoteheads->item,
|
||||
reversed, &result);
|
||||
if (clean < 0)
|
||||
exit(128);
|
||||
if (clean < 0) {
|
||||
rollback_lock_file(&lock);
|
||||
return 2;
|
||||
}
|
||||
if (write_locked_index(&the_index, &lock,
|
||||
COMMIT_LOCK | SKIP_IF_UNCHANGED))
|
||||
die(_("unable to write %s"), get_index_file());
|
||||
@ -1599,6 +1613,21 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||
*/
|
||||
refresh_cache(REFRESH_QUIET);
|
||||
if (allow_trivial && fast_forward != FF_ONLY) {
|
||||
/*
|
||||
* Must first ensure that index matches HEAD before
|
||||
* attempting a trivial merge.
|
||||
*/
|
||||
struct tree *head_tree = get_commit_tree(head_commit);
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
if (repo_index_has_changes(the_repository, head_tree,
|
||||
&sb)) {
|
||||
error(_("Your local changes to the following files would be overwritten by merge:\n %s"),
|
||||
sb.buf);
|
||||
strbuf_release(&sb);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* See if it is really trivial. */
|
||||
git_committer_info(IDENT_STRICT);
|
||||
printf(_("Trying really trivial in-index merge...\n"));
|
||||
@ -1655,12 +1684,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||
* tree in the index -- this means that the index must be in
|
||||
* sync with the head commit. The strategies are responsible
|
||||
* to ensure this.
|
||||
*
|
||||
* Stash away the local changes so that we can try more than one
|
||||
* and/or recover from merge strategies bailing while leaving the
|
||||
* index and working tree polluted.
|
||||
*/
|
||||
if (use_strategies_nr == 1 ||
|
||||
/*
|
||||
* Stash away the local changes so that we can try more than one.
|
||||
*/
|
||||
save_state(&stash))
|
||||
if (save_state(&stash))
|
||||
oidclr(&stash);
|
||||
|
||||
for (i = 0; !merge_was_ok && i < use_strategies_nr; i++) {
|
||||
|
Reference in New Issue
Block a user