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
This commit is contained in:
Joey Hess 2025-08-20 13:28:03 -04:00
commit fd89e611b2
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 59 additions and 22 deletions

View file

@ -524,15 +524,12 @@ propigateAdjustedCommits'
propigateAdjustedCommits' warnwhendiverged origbranch adj _commitsprevented = propigateAdjustedCommits' warnwhendiverged origbranch adj _commitsprevented =
inRepo (Git.Ref.sha basis) >>= \case inRepo (Git.Ref.sha basis) >>= \case
Just origsha -> catCommit currbranch >>= \case Just origsha -> catCommit currbranch >>= \case
Just currcommit -> Just currcommit -> do
newcommits >>= go origsha origsha False >>= \case newparent <- newcommits >>= go origsha origsha False
Left e -> do return
warning (UnquotedString e) ( Just newparent
return (Nothing, return ()) , rebase currcommit newparent
Right newparent -> return )
( Just newparent
, rebase currcommit newparent
)
Nothing -> return (Nothing, return ()) Nothing -> return (Nothing, return ())
Nothing -> do Nothing -> do
warning $ UnquotedString $ warning $ UnquotedString $
@ -553,16 +550,14 @@ propigateAdjustedCommits' warnwhendiverged origbranch adj _commitsprevented =
warning $ UnquotedString $ warning $ UnquotedString $
"Original branch " ++ fromRef origbranch ++ " has diverged from current adjusted branch " ++ fromRef currbranch "Original branch " ++ fromRef origbranch ++ " has diverged from current adjusted branch " ++ fromRef currbranch
_ -> inRepo $ Git.Branch.update' origbranch parent _ -> inRepo $ Git.Branch.update' origbranch parent
return (Right parent) return parent
go origsha parent pastadjcommit (sha:l) = catCommit sha >>= \case go origsha parent pastadjcommit (sha:l) = catCommit sha >>= \case
Just c Just c
| hasAdjustedBranchCommitMessage c -> | hasAdjustedBranchCommitMessage c ->
go origsha parent True l go origsha parent True l
| pastadjcommit -> | pastadjcommit -> do
reverseAdjustedCommit parent adj (sha, c) origbranch commit <- reverseAdjustedCommit parent adj (sha, c) origbranch
>>= \case go origsha commit pastadjcommit l
Left e -> return (Left e)
Right commit -> go origsha commit pastadjcommit l
_ -> go origsha parent pastadjcommit l _ -> go origsha parent pastadjcommit l
rebase currcommit newparent = do rebase currcommit newparent = do
-- Reuse the current adjusted tree, and reparent it -- 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 - The commit message, and the author and committer metadata are
- copied over from the basiscommit. However, any gpg signature - copied over from the basiscommit. However, any gpg signature
- will be lost, and any other headers are not copied either. -} - 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 reverseAdjustedCommit commitparent adj (csha, basiscommit) origbranch
| length (commitParent basiscommit) > 1 = return $ | length (commitParent basiscommit) > 1 = giveup $
Left $ "unable to propagate merge commit " ++ show csha ++ " back to " ++ show origbranch "unable to propagate merge commit " ++ show csha ++ " back to " ++ show origbranch
| otherwise = do | otherwise = do
cmode <- annexCommitMode <$> Annex.getGitConfig cmode <- annexCommitMode <$> Annex.getGitConfig
treesha <- reverseAdjustedTree commitparent adj csha treesha <- reverseAdjustedTree commitparent adj csha
@ -595,7 +590,7 @@ reverseAdjustedCommit commitparent adj (csha, basiscommit) origbranch
Git.Branch.commitTree cmode Git.Branch.commitTree cmode
[commitMessage basiscommit] [commitMessage basiscommit]
[commitparent] treesha [commitparent] treesha
return (Right revadjcommit) return revadjcommit
{- Adjusts the tree of the basis, changing only the files that the {- Adjusts the tree of the basis, changing only the files that the
- commit changed, and reverse adjusting those changes. - commit changed, and reverse adjusting those changes.

View file

@ -16,6 +16,10 @@ git-annex (10.20250722) UNRELEASED; urgency=medium
and display. and display.
* Improve behavior when there are special remotes configured with * Improve behavior when there are special remotes configured with
autoenable=yes with names that conflict with other remotes. 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. * Bump aws build dependency to 0.24.1.
* stack.yaml: Update to lts-24.2. * stack.yaml: Update to lts-24.2.

View file

@ -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.
"""]]

View file

@ -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 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 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, 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 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 When in an adjusted branch, using `git merge otherbranch` is often not
ideal, because merging a non-adjusted branch may lead to unnecessary ideal, because merging a non-adjusted branch may lead to unnecessary
merge conflicts, or add files in non-adjusted form. To avoid those merge conflicts, or add files in non-adjusted form. And such merges
problems, use `git annex merge otherbranch`. 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 Re-running this command with the same options
while inside the adjusted branch will update the adjusted branch while inside the adjusted branch will update the adjusted branch