git-mediate 1.1.0 → 1.2.0
raw patch · 9 files changed
+67/−35 lines, 9 filesnew-uploader
Files
- ChangeLog.md +8/−0
- README.md +17/−14
- git-mediate.cabal +1/−1
- src/Environment.hs +3/−3
- src/Main.hs +3/−1
- src/Opts.hs +1/−1
- src/Resolution.hs +30/−13
- src/ResolutionOpts.hs +3/−1
- stack.yaml +1/−1
ChangeLog.md view
@@ -1,3 +1,11 @@+## 1.2.0 / 2026.08.19++* Add optional automatic resolution of indentation-only conflicts+* Enable splitting conflicts at tilde markers by default+* Fix status reporting for split conflicts+* Prefer Git's `zdiff3` conflict style while continuing to accept `diff3`+* Avoid opening the editor when no unresolved conflicts remain+ ## 1.1.0 / 2024.09.20 * `--split-markers` option to help users split large conflicts to smaller parts
README.md view
@@ -1,11 +1,13 @@-# Introduction+# git-mediate [](https://hackage.haskell.org/package/git-mediate) [](https://formulae.brew.sh/formula/git-mediate) +## Introduction+ Handling conflicts is difficult! -One useful way to handle them, is to use git's diff3 conflict style:+One useful way to handle them, is to use git's {z,}diff3 conflict style: ```shell-git config --global merge.conflictstyle diff3+git config --global merge.conflictstyle zdiff3 ``` And then when you get a conflict, it looks like:@@ -66,26 +68,27 @@ When all conflicts have been resolved in a file, "git add" will be used on it automatically. -## Simpler case+### Simpler case You might just resolve the conflicts manually and remove the merge markers from all of the conflicts. In such a case, just run git-mediate, and it will "git add" the file for you. -# Installation+## Installation -## Using package managers+### Using package managers * macOS: `brew install git-mediate` * Linux (debian): `apt-get install git-mediate`+* Linux (arch): `yay -S git-mediate` (see https://aur.archlinux.org/packages/git-mediate) -## Using haskell-stack+### Using haskell-stack 1. Install [haskell stack](https://docs.haskellstack.org/en/stable/) 2. Run: `stack install git-mediate` -## From sources+### From sources Clone it: @@ -96,25 +99,25 @@ Option #2: Build & install using cabal: `cabal install` (make sure `~/.cabal/bin` is in your `$PATH`) -# Use+## Use Call the git-mediate from a git repository with conflicts. -# Additional features+## Additional features -## Open editor+### Open editor You can use the `-e` flag to invoke your `$EDITOR` on every conflicted file that could not be automatically resolved. -## Show conflict diffs+### Show conflict diffs Sometimes, the conflict is just a giant block of incomprehensible text next to another giant block of incomprehensible text. You can use the `-d` flag to show the conflict in diff-from-base form. Then, you can manually apply the changes you see in both the base and wherever needed, and use git-mediate again to make sure you've updated everything appropriately. -# License+## License -Copyright (C) 2014-2023 Eyal Lotem+Copyright (C) 2014-2024 Eyal Lotem This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
git-mediate.cabal view
@@ -2,7 +2,7 @@ -- further documentation, see https://cabal.readthedocs.io/ name: git-mediate-version: 1.1.0+version: 1.2.0 synopsis: Tool to help resolving git conflicts description: Git conflict resolution has never been easier .
src/Environment.hs view
@@ -36,7 +36,7 @@ setConflictStyle :: IO () setConflictStyle =- callProcess "git" ["config", "--global", "merge.conflictstyle", "diff3"]+ callProcess "git" ["config", "--global", "merge.conflictstyle", "zdiff3"] checkConflictStyle :: Options -> IO () checkConflictStyle opts =@@ -46,14 +46,14 @@ do unless opts.shouldSetConflictStyle $ fail $ concat- [ "merge.conflictstyle must be diff3 but is "+ [ "merge.conflictstyle must be zdiff3/diff3 but is " , show conflictStyle , ". Use -s to automatically set it globally" ] setConflictStyle newConflictStyle <- getConflictStyle- when (newConflictStyle /= "diff3") $+ when (newConflictStyle /= "zdiff3") $ fail $ concat [ "Attempt to set conflict style failed. Perhaps you have" , " an incorrect merge.conflictstyle configuration "
src/Main.hs view
@@ -65,7 +65,9 @@ do when (opts.shouldDumpDiffs || opts.shouldDumpDiff2) $ traverse_ (dumpDiffs colorEnable opts path (length conflicts)) (zip [1 ..] conflicts)- openEditor opts path ((Conflict.lineNo . Conflict.sideA . markers . head) conflicts)+ case conflicts of+ [] -> pure ()+ c:_ -> openEditor opts path ((Conflict.lineNo . Conflict.sideA . markers) c) overwrite :: FilePath -> String -> IO () overwrite fileName content =
src/Opts.hs view
@@ -48,7 +48,7 @@ <*> colorParser <*> O.switch ( O.long "style" <> O.short 's'- <> O.help "Configure git's global merge.conflictstyle to diff3 if needed"+ <> O.help "Configure git's global merge.conflictstyle to zdiff3 if needed" ) <*> O.optional ( O.strOption
src/Resolution.hs view
@@ -43,10 +43,24 @@ n = length base addedBothSides x y = [x <> drop n y | drop (length x - n) x == base && take n y == base] +resolveReduced :: ResolutionOptions -> Sides [String] -> Maybe [String]+resolveReduced opts sides+ | opts.indentation =+ map . (<>) <$> resolveGen prefixes <*> resolveGenLines opts unprefixed+ | otherwise = resolveGenLines opts sides+ where+ prefixes = takeWhile (== ' ') . commonPrefix <$> sides+ unprefixed = map . drop . length <$> prefixes <*> sides++commonPrefix :: Eq a => [[a]] -> [a]+commonPrefix [] = []+commonPrefix [x] = x+commonPrefix (x:xs) = map fst . takeWhile (uncurry (==)) . zip x $ commonPrefix xs+ resolveConflict :: ResolutionOptions -> Conflict -> Resolution resolveConflict opts c | matchTop == 0 && matchBottom == 0 || not opts.reduce =- maybe (NoResolution c) (Resolution . unlines) (resolveGenLines opts c.bodies)+ maybe (NoResolution c) (Resolution . unlines) (resolveReduced opts c.bodies) | otherwise = case resolveGenLines opts reduced.bodies of Just x -> Resolution $ formatRes x@@ -125,7 +139,7 @@ lineBreakFix :: Conflict -> Conflict lineBreakFix c- | any null (toList c.bodies)+ | any null c.bodies || allSame (toList endings) = c | otherwise = case resolveGen endings of@@ -149,17 +163,20 @@ foldMap go where go (Left line) = NewContent mempty (unlines [line])- go (Right conflict)- | opts.splitMarkers =- r <> splitProgress- | otherwise = resolve conflict- where- s = splitConflict conflict- r = foldMap resolve s- splitProgress =- case s of- (_:_:_) -> NewContent (Result 0 1 0) mempty- _ -> mempty+ go (Right conflict) =+ r+ { result =+ case parts of+ [_] -> r.result+ _ | r.result.failedToResolve + r.result.reducedConflicts > 0 ->+ mempty {reducedConflicts = 1} -- The split is a reduction+ | otherwise -> mempty {resolvedSuccessfully = 1}+ }+ where+ parts+ | opts.splitMarkers = splitConflict conflict+ | otherwise = [conflict]+ r = foldMap resolve parts resolve conflict = formatResolution $ resolveConflict opts $ (if opts.lineEndings then lineBreakFix else id) $
src/ResolutionOpts.hs view
@@ -14,6 +14,7 @@ , lineEndings :: Bool , addedLines :: Bool , splitMarkers :: Bool+ , indentation :: Bool } parser :: OptUtils.Parser ResolutionOptions@@ -27,7 +28,8 @@ <*> OptUtils.envSwitch "line-endings" True "line-ending characters conflict resolution" <*> OptUtils.envSwitch "lines-added-around" False "resolve conflicts where one change prepended lines to the base and the other appended"- <*> OptUtils.envSwitch "split-markers" False "split conflicts at tilde-split-markers"+ <*> OptUtils.envSwitch "split-markers" True "split conflicts at tilde-split-markers"+ <*> OptUtils.envSwitch "indentation" False "indentation conflict resolution" isResolving :: ResolutionOptions -> Bool isResolving o = o.trivial || o.reduce || isJust o.untabify || o.lineEndings || o.addedLines
stack.yaml view
@@ -1,4 +1,4 @@ flags: {} packages: - '.'-resolver: lts-22.30+resolver: lts-24.55