diff --git a/CHANGELOG b/CHANGELOG index a4f8eeb5a5..f48f93483b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ git-annex (8.20210715) UNRELEASED; urgency=medium (However, sync does still merge unrelated histories when importing trees from special remotes, and the assistant still merges unrelated histories.) + * sync, merge: Added --allow-unrelated-histories option, which + is the same as the git merge option. -- Joey Hess Wed, 14 Jul 2021 14:26:36 -0400 diff --git a/Command/Merge.hs b/Command/Merge.hs index aa8b0ddeb8..e7523f6252 100644 --- a/Command/Merge.hs +++ b/Command/Merge.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2011-2019 Joey Hess + - Copyright 2011-2021 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -12,22 +12,34 @@ import qualified Annex.Branch import qualified Git import qualified Git.Branch import Annex.CurrentBranch -import Command.Sync (prepMerge, mergeLocal, mergeConfig, merge, SyncOptions(..)) +import Command.Sync (prepMerge, mergeLocal, mergeConfig, merge, notOnlyAnnexOption, parseUnrelatedHistoriesOption) import Git.Types cmd :: Command cmd = command "merge" SectionMaintenance "merge changes from remotes" - (paramOptional paramRef) (withParams seek) + (paramOptional paramRef) (seek <$$> optParser) -seek :: CmdParams -> CommandSeek -seek [] = do - prepMerge - commandAction mergeAnnexBranch - commandAction mergeSyncedBranch -seek bs = do - prepMerge - forM_ bs (commandAction . mergeBranch . Git.Ref . encodeBS') +data MergeOptions = MergeOptions + { mergeBranches :: [String] + , allowUnrelatedHistories :: Bool + } + +optParser :: CmdParamsDesc -> Parser MergeOptions +optParser desc = MergeOptions + <$> cmdParams desc + <*> parseUnrelatedHistoriesOption + +seek :: MergeOptions -> CommandSeek +seek o + | mergeBranches o == [] = do + prepMerge + commandAction mergeAnnexBranch + commandAction (mergeSyncedBranch o) + | otherwise = do + prepMerge + forM_ (mergeBranches o) $ + commandAction . mergeBranch o . Git.Ref . encodeBS' mergeAnnexBranch :: CommandStart mergeAnnexBranch = starting "merge" ai si $ do @@ -39,17 +51,17 @@ mergeAnnexBranch = starting "merge" ai si $ do ai = ActionItemOther (Just (fromRef Annex.Branch.name)) si = SeekInput [] -mergeSyncedBranch :: CommandStart -mergeSyncedBranch = do - mc <- mergeConfig False +mergeSyncedBranch :: MergeOptions -> CommandStart +mergeSyncedBranch o = do + mc <- mergeConfig (allowUnrelatedHistories o) mergeLocal mc def =<< getCurrentBranch -mergeBranch :: Git.Ref -> CommandStart -mergeBranch r = starting "merge" ai si $ do +mergeBranch :: MergeOptions -> Git.Ref -> CommandStart +mergeBranch o r = starting "merge" ai si $ do currbranch <- getCurrentBranch - let o = def { notOnlyAnnexOption = True } - mc <- mergeConfig False - next $ merge currbranch mc o Git.Branch.ManualCommit r + mc <- mergeConfig (allowUnrelatedHistories o) + let so = def { notOnlyAnnexOption = True } + next $ merge currbranch mc so Git.Branch.ManualCommit r where ai = ActionItemOther (Just (Git.fromRef r)) si = SeekInput [] diff --git a/Command/Sync.hs b/Command/Sync.hs index f6c53c9514..5e5c85bd54 100644 --- a/Command/Sync.hs +++ b/Command/Sync.hs @@ -1,7 +1,7 @@ {- git-annex command - - Copyright 2011 Joachim Breitner - - Copyright 2011-2020 Joey Hess + - Copyright 2011-2021 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -24,6 +24,7 @@ module Command.Sync ( syncBranch, updateBranches, seekExportContent, + parseUnrelatedHistoriesOption, SyncOptions(..), ) where @@ -102,6 +103,7 @@ data SyncOptions = SyncOptions , cleanupOption :: Bool , keyOptions :: Maybe KeyOptions , resolveMergeOverride :: Bool + , allowUnrelatedHistories :: Bool } instance Default SyncOptions where @@ -120,6 +122,7 @@ instance Default SyncOptions where , cleanupOption = False , keyOptions = Nothing , resolveMergeOverride = False + , allowUnrelatedHistories = False } optParser :: CmdParamsDesc -> Parser SyncOptions @@ -177,6 +180,13 @@ optParser desc = SyncOptions <*> invertableSwitch "resolvemerge" True ( 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 -- have to be adjusted. @@ -196,6 +206,7 @@ instance DeferredParseClass SyncOptions where <*> pure (cleanupOption v) <*> pure (keyOptions v) <*> pure (resolveMergeOverride v) + <*> pure (allowUnrelatedHistories v) seek :: SyncOptions -> CommandSeek seek o = do @@ -218,7 +229,7 @@ seek' o = do commandAction (withbranch cleanupLocal) mapM_ (commandAction . withbranch . cleanupRemote) gitremotes else do - mc <- mergeConfig False + mc <- mergeConfig (allowUnrelatedHistories o) -- Syncing involves many actions, any of which -- can independently fail, without preventing diff --git a/Test.hs b/Test.hs index 39dd88c099..1ffed562cd 100644 --- a/Test.hs +++ b/Test.hs @@ -1983,7 +1983,7 @@ test_export_import_subdir = intmpclonerepo $ do testimport = do origbranch <- annexeval origBranch 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 -- of the repo. diff --git a/doc/git-annex-import.mdwn b/doc/git-annex-import.mdwn index 9ed9cc4855..39e42cefc8 100644 --- a/doc/git-annex-import.mdwn +++ b/doc/git-annex-import.mdwn @@ -42,19 +42,17 @@ currently checked out branch. For example: 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, -but using `git-annex merge` avoids a couple of gotchas. When using adjusted -branches, it adjusts the branch before merging from it. And it avoids -the merge failing on the first merge from an import due to unrelated -histories. +You could just as well use `git merge --allow-unrelated-histories myremote/master` +as the second step, but using `git-annex merge` avoids a couple of gotchas. +When using adjusted branches, it adjusts the branch before merging from it. -If you do use `git merge`, you can pass `--allow-unrelated-histories` the -first time you `git merge` from an import. Think of this as the remote -being a separate git repository with its own files. If you first -`git annex export` files to a remote, and then `git annex import` from it, -you won't need that option. +The --allow-unrelated-histories option is needed for at least the first +merge of an imported remote tracking branch, since the branch's history is +not connected. Think of this as the remote being a separate git repository +with its own files. If you first `git annex export` files to a remote, and +then `git annex import` from it, you won't need that option. 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 diff --git a/doc/git-annex-merge.mdwn b/doc/git-annex-merge.mdwn index 7fc4f44e2a..153e2b93d4 100644 --- a/doc/git-annex-merge.mdwn +++ b/doc/git-annex-merge.mdwn @@ -22,7 +22,12 @@ will not be done. # 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 diff --git a/doc/git-annex-sync.mdwn b/doc/git-annex-sync.mdwn index f3c171f0ae..2ad535a99d 100644 --- a/doc/git-annex-sync.mdwn +++ b/doc/git-annex-sync.mdwn @@ -150,6 +150,11 @@ have the same value as the currently checked out branch. less efficient. When --content is synced, the files are processed 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` By default, merge conflicts are automatically handled by sync. When two