1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-25 05:26:20 +02:00

checkout.txt: note about losing staged changes with --merge

If you have staged changes in path A and perform 'checkout
--merge' (which could result in conflicts in a totally unrelated path
B), changes in A will be gone. Which is unexpected. We are supposed
to keep all changes, or kick and scream otherwise.

This is the result of how --merge is implemented, from the very first
day in 1be0659efc (checkout: merge local modifications while switching
branches., 2006-01-12):

1. a merge is done, unmerged entries are collected
2. a hard switch to a new branch is done, then unmerged entries added
   back

There is no trivial fix for this. Going with 3-way merge one file at a
time loses rename detection. Going with 3-way merge by trees requires
teaching the algorithm to pick up staged changes. And even if we detect
staged changes with --merge and abort for safety, an option to continue
--merge is very weird. Such an option would keep worktree changes, but
drop staged changes.

Because the problem has been with us since the introduction of --merge
and everybody has been pretty happy (except Phillip, who found this
problem), I'll just take a note here to acknowledge it and wait for
merge wizards to come in and work their magic. There may be a way
forward [1].

[1] CABPp-BFoL_U=bzON4SEMaQSKU2TKwnOgNqjt5MUaOejTKGUJxw@mail.gmail.com

Reported-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2019-03-19 16:39:10 +07:00 committed by Junio C Hamano
parent aeb582a983
commit a7256debd4
2 changed files with 11 additions and 0 deletions

View File

@ -242,6 +242,8 @@ should result in deletion of the path).
+
When checking out paths from the index, this option lets you recreate
the conflicted merge in the specified paths.
+
When switching branches with `--merge`, staged changes may be lost.
--conflict=<style>::
The same as --merge option above, but changes the way the

View File

@ -676,6 +676,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
struct tree *result;
struct tree *work;
struct merge_options o;
struct strbuf sb = STRBUF_INIT;
if (!opts->merge)
return 1;
@ -686,6 +688,13 @@ static int merge_working_tree(const struct checkout_opts *opts,
if (!old_branch_info->commit)
return 1;
if (repo_index_has_changes(the_repository,
get_commit_tree(old_branch_info->commit),
&sb))
warning(_("staged changes in the following files may be lost: %s"),
sb.buf);
strbuf_release(&sb);
/* Do more real merge */
/*