From ab5af825db8beaf623f8ac95e4b4179ec1b9569e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Mon, 18 Mar 2019 18:38:22 +0700 Subject: unpack-trees: fix oneway_merge accidentally carry over stage index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phillip found out that 'git checkout -f ' does not restore conflict/unmerged files correctly. All tracked files should be taken from and all non-zero stages removed. Most of this is true, except that the final file could be in stage one instead of zero. "checkout -f" (among other commands) does this with one-way merge, which is supposed to take stat info from the index and everything else from the given tree. The add_entry(.., old, ...) call in oneway_merge() though will keep stage index from the index. This is normally not a problem if the entry from the index is normal (stage #0). But if there is a conflict, stage #0 does not exist and we'll get stage #1 entry as "old" variable, which gets recorded in the final index. Fix it by clearing stage mask. This bug probably comes from b5b425074e (git-read-tree: make one-way merge also honor the "update" flag, 2005-06-07). Before this commit, we may create the final ("dst") index entry from the one in index, but we do clear CE_STAGEMASK. I briefly checked two- and three-way merge functions. I think we don't have the same problem in those. Reported-by: Phillip Wood Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- t/t2023-checkout-m.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 't/t2023-checkout-m.sh') diff --git a/t/t2023-checkout-m.sh b/t/t2023-checkout-m.sh index 7e18985134..fca3f85824 100755 --- a/t/t2023-checkout-m.sh +++ b/t/t2023-checkout-m.sh @@ -46,4 +46,28 @@ test_expect_success '-m restores 3-way conflicted+resolved file' ' test_cmp both.txt.conflicted.cleaned both.txt.cleaned ' +test_expect_success 'force checkout a conflict file creates stage zero entry' ' + git init co-force && + ( + cd co-force && + echo a >a && + git add a && + git commit -ama && + A_OBJ=$(git rev-parse :a) && + git branch topic && + echo b >a && + git commit -amb && + B_OBJ=$(git rev-parse :a) && + git checkout topic && + echo c >a && + C_OBJ=$(git hash-object a) && + git checkout -m master && + test_cmp_rev :1:a $A_OBJ && + test_cmp_rev :2:a $B_OBJ && + test_cmp_rev :3:a $C_OBJ && + git checkout -f topic && + test_cmp_rev :0:a $A_OBJ + ) +' + test_done -- cgit v1.2.3