make automerge behavior when one side deleted explict

This does not actually change how the merge conflict is resolved when
one side deleted the file, but it was not documented before, and I think
it only worked by accident.

This commit was sponsored by Brett Eisenberg on Patreon.
This commit is contained in:
Joey Hess 2020-09-07 12:01:03 -04:00
parent 13fdba133f
commit a360437215
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 53 additions and 14 deletions

View file

@ -143,10 +143,10 @@ resolveMerge' unstagedmap (Just us) them inoverlay u = do
kthem <- getkey LsFiles.valThem
case (kus, kthem) of
-- Both sides of conflict are annexed files
(Just keyUs, Just keyThem)
(Right (Just keyUs), Right (Just keyThem))
| keyUs /= keyThem -> resolveby [keyUs, keyThem] $ do
makeannexlink keyUs LsFiles.valUs
makeannexlink keyThem LsFiles.valThem
makevariantannexlink keyUs LsFiles.valUs
makevariantannexlink keyThem LsFiles.valThem
-- cleanConflictCruft can't handle unlocked
-- files, so delete here.
unless inoverlay $
@ -162,22 +162,41 @@ resolveMerge' unstagedmap (Just us) them inoverlay u = do
else makepointer keyUs file (combinedmodes)
return ([keyUs, keyThem], Just file)
-- Our side is annexed file, other side is not.
(Just keyUs, Nothing) -> resolveby [keyUs] $ do
-- Make the annexed file into a variant file and graft in the
-- other file as it was.
(Right (Just keyUs), Right Nothing) -> resolveby [keyUs] $ do
graftin them file LsFiles.valThem LsFiles.valThem LsFiles.valUs
makeannexlink keyUs LsFiles.valUs
makevariantannexlink keyUs LsFiles.valUs
-- Our side is not annexed file, other side is.
(Nothing, Just keyThem) -> resolveby [keyThem] $ do
(Right Nothing, Right (Just keyThem)) -> resolveby [keyThem] $ do
graftin us file LsFiles.valUs LsFiles.valUs LsFiles.valThem
makeannexlink keyThem LsFiles.valThem
makevariantannexlink keyThem LsFiles.valThem
-- Neither side is annexed file; cannot resolve.
(Nothing, Nothing) -> return ([], Nothing)
(Right Nothing, Right Nothing) -> cannotresolve
-- Other side deleted the file, our side is an annexed
-- file. Make it a variant.
(Right (Just keyUs), Left ()) -> resolveby [keyUs] $
makevariantannexlink keyUs LsFiles.valThem
-- Our side deleted the file, other side is an annexed
-- file. Make it a variant.
(Left (), Right (Just keyThem)) -> resolveby [keyThem] $
makevariantannexlink keyThem LsFiles.valThem
-- One side deleted the file, other side is not an annexed
-- file; cannot resolve.
(Left (), Right Nothing) -> cannotresolve
(Right Nothing, Left()) -> cannotresolve
-- Both deleted, so it's not really a conflict. Probably
-- impossible for this to happen.
(Left (), Left ()) -> cannotresolve
where
file = fromRawFilePath $ LsFiles.unmergedFile u
cannotresolve = return ([], Nothing)
getkey select =
case select (LsFiles.unmergedSha u) of
Just sha -> catKey sha
Nothing -> return Nothing
Just sha -> Right <$> catKey sha
Nothing -> return (Left ())
islocked select = select (LsFiles.unmergedTreeItemType u) == Just TreeSymlink
@ -190,7 +209,7 @@ resolveMerge' unstagedmap (Just us) them inoverlay u = do
theirmode = fromTreeItemType
<$> LsFiles.valThem (LsFiles.unmergedTreeItemType u)
makeannexlink key select
makevariantannexlink key select
| islocked select = makesymlink key dest
| otherwise = makepointer key dest destmode
where

View file

@ -8,15 +8,27 @@ git annex resolvemerge
# DESCRIPTION
Resolves a conflicted merge, by adding both conflicting versions of the
file to the tree, using variants of their filename. This is done
Automatically resolves a conflicted merge. This is done
automatically when using `git annex sync` or `git annex merge`.
When two trees being merged contain conflicting versions of an annexed
file, the merge conflict will be resolved by adding both versions to the
tree, using variants of the filename.
When one tree modified the file, and the other tree deleted the file,
the merge conflict will be resolved by adding the modified file using a
variant of the filename, leaving the original filename deleted.
When the merge conflict involves a file that is annexed in one
tree, but is not annexed in the other tree, it is
resolved by keeping the non-annexed file as-is, and adding the annexed
version using a variant of the filename.
Note that only merge conflicts that involve one or more annexed files
are resolved. Merge conflicts between two files that are not annexed
will not be automatically resolved.
# EXAMPLE
# EXAMPLES
Suppose Alice commits a change to annexed file `foo`, and Bob commits
a different change to the same file `foo`.
@ -35,6 +47,14 @@ The user can then examine the two variants of the file, and either merge
the two changes into a single file, or rename one of them back to `foo`
and delete the other.
Now suppose Alice commits a change to annexed file `bar`, while Bob commits
a deletion of the same file `bar`. Merging will fail. Running
`git annex resolvemerge` in this situation will resolve the merge conflict
by making a file with a name like `bar.variant-421f` containing Alice's
version. The `bar` file remains deleted. The user can later examine the
variant of the file and either rename it back to `bar`, or decide to delete
it too.
# SEE ALSO
[[git-annex]](1)