From fd89e611b2310b46368c91bcd79999b0ba8462a3 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 20 Aug 2025 13:28:03 -0400 Subject: [PATCH] error out when another branch has been manually merged into the adjusted branch This avoids losing the merge commit when re-running git-annex adjust in the adjusted branch. It also makes git-annex sync error out, rather than displaying a warning and exiting successfully. Sponsored-by: Leon Schuermann on Patreon --- Annex/AdjustedBranch.hs | 33 +++++++---------- CHANGELOG | 4 ++ ..._5b9c6c1966f967ff417c2acc39cfada4._comment | 37 +++++++++++++++++++ doc/git-annex-adjust.mdwn | 7 ++-- 4 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 doc/bugs/Re-Adjust_Loses_Commits/comment_2_5b9c6c1966f967ff417c2acc39cfada4._comment diff --git a/Annex/AdjustedBranch.hs b/Annex/AdjustedBranch.hs index 95bd8cfc34..4f72cbd979 100644 --- a/Annex/AdjustedBranch.hs +++ b/Annex/AdjustedBranch.hs @@ -524,15 +524,12 @@ propigateAdjustedCommits' propigateAdjustedCommits' warnwhendiverged origbranch adj _commitsprevented = inRepo (Git.Ref.sha basis) >>= \case Just origsha -> catCommit currbranch >>= \case - Just currcommit -> - newcommits >>= go origsha origsha False >>= \case - Left e -> do - warning (UnquotedString e) - return (Nothing, return ()) - Right newparent -> return - ( Just newparent - , rebase currcommit newparent - ) + Just currcommit -> do + newparent <- newcommits >>= go origsha origsha False + return + ( Just newparent + , rebase currcommit newparent + ) Nothing -> return (Nothing, return ()) Nothing -> do warning $ UnquotedString $ @@ -553,16 +550,14 @@ propigateAdjustedCommits' warnwhendiverged origbranch adj _commitsprevented = warning $ UnquotedString $ "Original branch " ++ fromRef origbranch ++ " has diverged from current adjusted branch " ++ fromRef currbranch _ -> inRepo $ Git.Branch.update' origbranch parent - return (Right parent) + return parent go origsha parent pastadjcommit (sha:l) = catCommit sha >>= \case Just c | hasAdjustedBranchCommitMessage c -> go origsha parent True l - | pastadjcommit -> - reverseAdjustedCommit parent adj (sha, c) origbranch - >>= \case - Left e -> return (Left e) - Right commit -> go origsha commit pastadjcommit l + | pastadjcommit -> do + commit <- reverseAdjustedCommit parent adj (sha, c) origbranch + go origsha commit pastadjcommit l _ -> go origsha parent pastadjcommit l rebase currcommit newparent = do -- Reuse the current adjusted tree, and reparent it @@ -582,10 +577,10 @@ rebaseOnTopMsg = "rebasing adjusted branch on top of updated original branch" - The commit message, and the author and committer metadata are - copied over from the basiscommit. However, any gpg signature - will be lost, and any other headers are not copied either. -} -reverseAdjustedCommit :: Sha -> Adjustment -> (Sha, Commit) -> OrigBranch -> Annex (Either String Sha) +reverseAdjustedCommit :: Sha -> Adjustment -> (Sha, Commit) -> OrigBranch -> Annex Sha reverseAdjustedCommit commitparent adj (csha, basiscommit) origbranch - | length (commitParent basiscommit) > 1 = return $ - Left $ "unable to propagate merge commit " ++ show csha ++ " back to " ++ show origbranch + | length (commitParent basiscommit) > 1 = giveup $ + "unable to propagate merge commit " ++ show csha ++ " back to " ++ show origbranch | otherwise = do cmode <- annexCommitMode <$> Annex.getGitConfig treesha <- reverseAdjustedTree commitparent adj csha @@ -595,7 +590,7 @@ reverseAdjustedCommit commitparent adj (csha, basiscommit) origbranch Git.Branch.commitTree cmode [commitMessage basiscommit] [commitparent] treesha - return (Right revadjcommit) + return revadjcommit {- Adjusts the tree of the basis, changing only the files that the - commit changed, and reverse adjusting those changes. diff --git a/CHANGELOG b/CHANGELOG index adba28c4d4..a43bae3fd4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,10 @@ git-annex (10.20250722) UNRELEASED; urgency=medium and display. * Improve behavior when there are special remotes configured with autoenable=yes with names that conflict with other remotes. + * adjust: When another branch has been manually merged into the adjusted + branch, re-adjusting errors out, rather than losing that merge commit. + * sync: When another branch has been manually merged into an adjusted + branch, error out rather than only displaying a warning. * Bump aws build dependency to 0.24.1. * stack.yaml: Update to lts-24.2. diff --git a/doc/bugs/Re-Adjust_Loses_Commits/comment_2_5b9c6c1966f967ff417c2acc39cfada4._comment b/doc/bugs/Re-Adjust_Loses_Commits/comment_2_5b9c6c1966f967ff417c2acc39cfada4._comment new file mode 100644 index 0000000000..b3ff29c440 --- /dev/null +++ b/doc/bugs/Re-Adjust_Loses_Commits/comment_2_5b9c6c1966f967ff417c2acc39cfada4._comment @@ -0,0 +1,37 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 2""" + date="2025-08-20T16:34:25Z" + content=""" +Thanks for bumping this. It was in my backlog. I've taken a look at it now. + +Note that you can use the reflog to get back to the missing commits. + +The [[git-annex-adjust]] warns about merging into an adjusted branch. And +suggests to use `git-annex merge` to merge a branch into an adjusted +branch. Which avoids this problem. + +Probably the best thing for it to do in this situation is to fail in a way +that leaves the adjusted branch as-is. The user can then address the +problem, eg by resetting the adjusted branch to a point before the merge +and doing the merge some other way. + +It would be difficult to handle propagating a merge commit back to the +original branch. Usually when on an adjusted branch, any commit of annexed +files can be assumed to have the adjustment (eg unlocking) applied to the +files. And so reversing the adjustment will yield the desired state (eg +locked files). But a merge commit may not be of another adjusted branch, +it could be a non-adjusted branch. Or it could be a branch with a different +adjustment applied to it. Reversing the adjustment would then do the wrong +thing. + +Consider for example, if the --unlock adjustment were used. But then a +branch adjusted with --hide-missing were merged in. This is basically +indistingushable from merging in a branch where some unwanted annexed file +is removed. + +Also, it looks at the diff of changes made in a commit to know which +annexed files were changed and reverse adjusts those files. In a merge +commit, it's not clear which of the multiple parents it should diff +against. +"""]] diff --git a/doc/git-annex-adjust.mdwn b/doc/git-annex-adjust.mdwn index fd573ec904..55f7f646e7 100644 --- a/doc/git-annex-adjust.mdwn +++ b/doc/git-annex-adjust.mdwn @@ -21,7 +21,7 @@ to a public branch with commands like `git-annex unlock`. While in the adjusted branch, you can use git-annex and git commands as usual. Any commits that you make will initially only be made to the -adjusted branch. +adjusted branch. To propagate commits from the adjusted branch back to the original branch, and to other repositories, as well as to merge in changes from other @@ -31,8 +31,9 @@ made by this command. When in an adjusted branch, using `git merge otherbranch` is often not ideal, because merging a non-adjusted branch may lead to unnecessary -merge conflicts, or add files in non-adjusted form. To avoid those -problems, use `git annex merge otherbranch`. +merge conflicts, or add files in non-adjusted form. And such merges +cannot be propagated from the adjusted branch back to the original branch. +To avoid those problems, use `git annex merge otherbranch`. Re-running this command with the same options while inside the adjusted branch will update the adjusted branch -- 2.30.2