Skip to content

Commit a7256de

Browse files
pcloudsgitster
authored andcommitted
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 1be0659 (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 <[email protected]> Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent aeb582a commit a7256de

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

Documentation/git-checkout.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ should result in deletion of the path).
242242
+
243243
When checking out paths from the index, this option lets you recreate
244244
the conflicted merge in the specified paths.
245+
+
246+
When switching branches with `--merge`, staged changes may be lost.
245247

246248
--conflict=<style>::
247249
The same as --merge option above, but changes the way the

builtin/checkout.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
676676
struct tree *result;
677677
struct tree *work;
678678
struct merge_options o;
679+
struct strbuf sb = STRBUF_INIT;
680+
679681
if (!opts->merge)
680682
return 1;
681683

@@ -686,6 +688,13 @@ static int merge_working_tree(const struct checkout_opts *opts,
686688
if (!old_branch_info->commit)
687689
return 1;
688690

691+
if (repo_index_has_changes(the_repository,
692+
get_commit_tree(old_branch_info->commit),
693+
&sb))
694+
warning(_("staged changes in the following files may be lost: %s"),
695+
sb.buf);
696+
strbuf_release(&sb);
697+
689698
/* Do more real merge */
690699

691700
/*

0 commit comments

Comments
 (0)