sync, merge: Added --allow-unrelated-histories option

Which is the same as the git merge option.

After last commit, this turns out to be needed in the test suite, and when
doing git-annex import from special remote, followed by a git-annex merge.

Sponsored-by: Svenne Krap on Patreon
This commit is contained in:
Joey Hess 2021-07-19 12:08:24 -04:00
parent b6bea0d3f2
commit 3d50b47ded
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 67 additions and 34 deletions

View file

@ -14,6 +14,8 @@ git-annex (8.20210715) UNRELEASED; urgency=medium
(However, sync does still merge unrelated histories when importing (However, sync does still merge unrelated histories when importing
trees from special remotes, and the assistant still merges unrelated trees from special remotes, and the assistant still merges unrelated
histories.) histories.)
* sync, merge: Added --allow-unrelated-histories option, which
is the same as the git merge option.
-- Joey Hess <id@joeyh.name> Wed, 14 Jul 2021 14:26:36 -0400 -- Joey Hess <id@joeyh.name> Wed, 14 Jul 2021 14:26:36 -0400

View file

@ -1,6 +1,6 @@
{- git-annex command {- git-annex command
- -
- Copyright 2011-2019 Joey Hess <id@joeyh.name> - Copyright 2011-2021 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -12,22 +12,34 @@ import qualified Annex.Branch
import qualified Git import qualified Git
import qualified Git.Branch import qualified Git.Branch
import Annex.CurrentBranch import Annex.CurrentBranch
import Command.Sync (prepMerge, mergeLocal, mergeConfig, merge, SyncOptions(..)) import Command.Sync (prepMerge, mergeLocal, mergeConfig, merge, notOnlyAnnexOption, parseUnrelatedHistoriesOption)
import Git.Types import Git.Types
cmd :: Command cmd :: Command
cmd = command "merge" SectionMaintenance cmd = command "merge" SectionMaintenance
"merge changes from remotes" "merge changes from remotes"
(paramOptional paramRef) (withParams seek) (paramOptional paramRef) (seek <$$> optParser)
seek :: CmdParams -> CommandSeek data MergeOptions = MergeOptions
seek [] = do { mergeBranches :: [String]
, allowUnrelatedHistories :: Bool
}
optParser :: CmdParamsDesc -> Parser MergeOptions
optParser desc = MergeOptions
<$> cmdParams desc
<*> parseUnrelatedHistoriesOption
seek :: MergeOptions -> CommandSeek
seek o
| mergeBranches o == [] = do
prepMerge prepMerge
commandAction mergeAnnexBranch commandAction mergeAnnexBranch
commandAction mergeSyncedBranch commandAction (mergeSyncedBranch o)
seek bs = do | otherwise = do
prepMerge prepMerge
forM_ bs (commandAction . mergeBranch . Git.Ref . encodeBS') forM_ (mergeBranches o) $
commandAction . mergeBranch o . Git.Ref . encodeBS'
mergeAnnexBranch :: CommandStart mergeAnnexBranch :: CommandStart
mergeAnnexBranch = starting "merge" ai si $ do mergeAnnexBranch = starting "merge" ai si $ do
@ -39,17 +51,17 @@ mergeAnnexBranch = starting "merge" ai si $ do
ai = ActionItemOther (Just (fromRef Annex.Branch.name)) ai = ActionItemOther (Just (fromRef Annex.Branch.name))
si = SeekInput [] si = SeekInput []
mergeSyncedBranch :: CommandStart mergeSyncedBranch :: MergeOptions -> CommandStart
mergeSyncedBranch = do mergeSyncedBranch o = do
mc <- mergeConfig False mc <- mergeConfig (allowUnrelatedHistories o)
mergeLocal mc def =<< getCurrentBranch mergeLocal mc def =<< getCurrentBranch
mergeBranch :: Git.Ref -> CommandStart mergeBranch :: MergeOptions -> Git.Ref -> CommandStart
mergeBranch r = starting "merge" ai si $ do mergeBranch o r = starting "merge" ai si $ do
currbranch <- getCurrentBranch currbranch <- getCurrentBranch
let o = def { notOnlyAnnexOption = True } mc <- mergeConfig (allowUnrelatedHistories o)
mc <- mergeConfig False let so = def { notOnlyAnnexOption = True }
next $ merge currbranch mc o Git.Branch.ManualCommit r next $ merge currbranch mc so Git.Branch.ManualCommit r
where where
ai = ActionItemOther (Just (Git.fromRef r)) ai = ActionItemOther (Just (Git.fromRef r))
si = SeekInput [] si = SeekInput []

View file

@ -1,7 +1,7 @@
{- git-annex command {- git-annex command
- -
- Copyright 2011 Joachim Breitner <mail@joachim-breitner.de> - Copyright 2011 Joachim Breitner <mail@joachim-breitner.de>
- Copyright 2011-2020 Joey Hess <id@joeyh.name> - Copyright 2011-2021 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -24,6 +24,7 @@ module Command.Sync (
syncBranch, syncBranch,
updateBranches, updateBranches,
seekExportContent, seekExportContent,
parseUnrelatedHistoriesOption,
SyncOptions(..), SyncOptions(..),
) where ) where
@ -102,6 +103,7 @@ data SyncOptions = SyncOptions
, cleanupOption :: Bool , cleanupOption :: Bool
, keyOptions :: Maybe KeyOptions , keyOptions :: Maybe KeyOptions
, resolveMergeOverride :: Bool , resolveMergeOverride :: Bool
, allowUnrelatedHistories :: Bool
} }
instance Default SyncOptions where instance Default SyncOptions where
@ -120,6 +122,7 @@ instance Default SyncOptions where
, cleanupOption = False , cleanupOption = False
, keyOptions = Nothing , keyOptions = Nothing
, resolveMergeOverride = False , resolveMergeOverride = False
, allowUnrelatedHistories = False
} }
optParser :: CmdParamsDesc -> Parser SyncOptions optParser :: CmdParamsDesc -> Parser SyncOptions
@ -177,6 +180,13 @@ optParser desc = SyncOptions
<*> invertableSwitch "resolvemerge" True <*> invertableSwitch "resolvemerge" True
( help "do not automatically resolve merge conflicts" ( help "do not automatically resolve merge conflicts"
) )
<*> parseUnrelatedHistoriesOption
parseUnrelatedHistoriesOption :: Parser Bool
parseUnrelatedHistoriesOption =
invertableSwitch "allow-unrelated-histories" False
( help "allow merging unrelated histories"
)
-- Since prepMerge changes the working directory, FilePath options -- Since prepMerge changes the working directory, FilePath options
-- have to be adjusted. -- have to be adjusted.
@ -196,6 +206,7 @@ instance DeferredParseClass SyncOptions where
<*> pure (cleanupOption v) <*> pure (cleanupOption v)
<*> pure (keyOptions v) <*> pure (keyOptions v)
<*> pure (resolveMergeOverride v) <*> pure (resolveMergeOverride v)
<*> pure (allowUnrelatedHistories v)
seek :: SyncOptions -> CommandSeek seek :: SyncOptions -> CommandSeek
seek o = do seek o = do
@ -218,7 +229,7 @@ seek' o = do
commandAction (withbranch cleanupLocal) commandAction (withbranch cleanupLocal)
mapM_ (commandAction . withbranch . cleanupRemote) gitremotes mapM_ (commandAction . withbranch . cleanupRemote) gitremotes
else do else do
mc <- mergeConfig False mc <- mergeConfig (allowUnrelatedHistories o)
-- Syncing involves many actions, any of which -- Syncing involves many actions, any of which
-- can independently fail, without preventing -- can independently fail, without preventing

View file

@ -1983,7 +1983,7 @@ test_export_import_subdir = intmpclonerepo $ do
testimport = do testimport = do
origbranch <- annexeval origBranch origbranch <- annexeval origBranch
git_annex "import" [origbranch++":"++subdir, "--from", "foo"] "import of subdir" git_annex "import" [origbranch++":"++subdir, "--from", "foo"] "import of subdir"
git_annex "merge" ["foo/master"] "git annex merge foo/master" git_annex "merge" ["foo/master", "--allow-unrelated-histories"] "git annex merge foo/master"
-- Make sure that import did not import the file to the top -- Make sure that import did not import the file to the top
-- of the repo. -- of the repo.

View file

@ -42,19 +42,17 @@ currently checked out branch.
For example: For example:
git annex import master --from myremote git annex import master --from myremote
git annex merge myremote/master git annex merge --allow-unrelated-histories myremote/master
You could just as well use `git merge myremote/master` as the second step, You could just as well use `git merge --allow-unrelated-histories myremote/master`
but using `git-annex merge` avoids a couple of gotchas. When using adjusted as the second step, but using `git-annex merge` avoids a couple of gotchas.
branches, it adjusts the branch before merging from it. And it avoids When using adjusted branches, it adjusts the branch before merging from it.
the merge failing on the first merge from an import due to unrelated
histories.
If you do use `git merge`, you can pass `--allow-unrelated-histories` the The --allow-unrelated-histories option is needed for at least the first
first time you `git merge` from an import. Think of this as the remote merge of an imported remote tracking branch, since the branch's history is
being a separate git repository with its own files. If you first not connected. Think of this as the remote being a separate git repository
`git annex export` files to a remote, and then `git annex import` from it, with its own files. If you first `git annex export` files to a remote, and
you won't need that option. then `git annex import` from it, you won't need that option.
You can import into a subdirectory, using the "branch:subdir" syntax. For You can import into a subdirectory, using the "branch:subdir" syntax. For
example, if "camera" is a special remote that accesses a camera, and you example, if "camera" is a special remote that accesses a camera, and you

View file

@ -22,7 +22,12 @@ will not be done.
# OPTIONS # OPTIONS
* The [[git-annex-common-options]](1) can be used. * `--allow-unrelated-histories`, `--no-allow-unrelated-histories`
Passed on to `git merge`, to control whether or not to merge
histories that do not share a common ancestor.
* Also, the [[git-annex-common-options]](1) can be used.
# SEE ALSO # SEE ALSO

View file

@ -150,6 +150,11 @@ have the same value as the currently checked out branch.
less efficient. When --content is synced, the files are processed less efficient. When --content is synced, the files are processed
in parallel as well. in parallel as well.
* `--allow-unrelated-histories`, `--no-allow-unrelated-histories`
Passed on to `git merge`, to control whether or not to merge
histories that do not share a common ancestor.
* `--resolvemerge`, `--no-resolvemerge` * `--resolvemerge`, `--no-resolvemerge`
By default, merge conflicts are automatically handled by sync. When two By default, merge conflicts are automatically handled by sync. When two