Compare commits
	
		
			15 commits
		
	
	
		
			aea372a87d
			...
			f294df0e69
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f294df0e69 | ||
|  | 6e19cd7267 | ||
|  | 6126e1c976 | ||
|   | 10777c32f6 | ||
|   | 6beaeec8e7 | ||
|   | 6682b5ed37 | ||
|  | 6cdd70feaf | ||
|   | 50a3d08aa8 | ||
|  | 2ed3f68748 | ||
|  | b0ffa1a3e6 | ||
|  | ecb03d3be4 | ||
|  | e6ae4a04d3 | ||
|  | 13b5da3d74 | ||
|  | bb194535e0 | ||
|  | 8241b556b1 | 
							
								
								
									
										1
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -14,7 +14,6 @@ jobs: | ||||||
|       matrix: |       matrix: | ||||||
|         os: [ubuntu-22.04, macos-15] |         os: [ubuntu-22.04, macos-15] | ||||||
|         ghc: |         ghc: | ||||||
|           - "9.6" |  | ||||||
|           - "9.12" |           - "9.12" | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v4 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| # Revision history for werge |  | ||||||
| 
 |  | ||||||
| ## 0.1.0.0 -- YYYY-mm-dd |  | ||||||
| 
 |  | ||||||
| * First version. Released on an unsuspecting world. |  | ||||||
							
								
								
									
										2
									
								
								Main.hs
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Main.hs
									
									
									
									
									
								
							|  | @ -385,4 +385,4 @@ main = catch go bad | ||||||
|     go = parseOpts >>= uncurry (flip runCmd) |     go = parseOpts >>= uncurry (flip runCmd) | ||||||
|     bad e = do |     bad e = do | ||||||
|       hPutStrLn stderr $ "fatal: " ++ displayException (e :: IOException) |       hPutStrLn stderr $ "fatal: " ++ displayException (e :: IOException) | ||||||
|       exitWith (ExitFailure 2) |       exitWith (ExitFailure 129) | ||||||
|  |  | ||||||
							
								
								
									
										149
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								README.md
									
									
									
									
									
								
							|  | @ -21,21 +21,52 @@ Separate `diff`&`patch` functionality is provided too for sending | ||||||
| token-granularity patches. (The patches are similar to what `git diff | token-granularity patches. (The patches are similar to what `git diff | ||||||
| --word-diff` produces, but can be applied to files.) | --word-diff` produces, but can be applied to files.) | ||||||
| 
 | 
 | ||||||
|  | ## Installation | ||||||
|  | 
 | ||||||
|  | - To build from source, clone the repo and run `cabal install` in the directory | ||||||
|  |   (you need [a way to compile Haskell](https://www.haskell.org/downloads/)). | ||||||
|  | - [Releases](https://github.com/exaexa/werge/releases) come with prebuilt | ||||||
|  |   binaries that you may download and run as-is on many Linuxes and Macs. | ||||||
|  | 
 | ||||||
|  | Running of `werge` requires working installations of `diff` and `patch` | ||||||
|  | compatible with the ones from [GNU | ||||||
|  | diffutils](https://www.gnu.org/software/diffutils/): | ||||||
|  | - Most Linux distributions contain the correct diffutils | ||||||
|  | - On BSDs you should be able to install these from Ports | ||||||
|  |   ([FreeBSD](https://cgit.freebsd.org/ports/tree/textproc/diffutils), | ||||||
|  |   [OpenBSD](https://openports.eu/ports/textproc/gdiff)) | ||||||
|  | - On Macs, install [diffutils from | ||||||
|  |   brew](https://formulae.brew.sh/formula/diffutils). | ||||||
|  | 
 | ||||||
|  | In any other case, you may set up a path to any compatible `diff` and `patch` | ||||||
|  | (or suitable wrapper scripts) via environment variables `WERGE_DIFF` and | ||||||
|  | `WERGE_PATCH`. (If required, the same applies for `WERGE_GIT`.) | ||||||
|  | 
 | ||||||
|  | ### Editor integration | ||||||
|  | 
 | ||||||
|  | There's a `vim` syntax highlighting file in `vim/werge.vim`. To install, simply | ||||||
|  | copy it to your local `vim` syntax configuration directory (usually to | ||||||
|  | `~/.vim/syntax/werge.vim`). Then, you can activate the syntax in vim with: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | :set syn=werge | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Demo | ## Demo | ||||||
| 
 | 
 | ||||||
| Original (`old` file): | ##### Original (`old` file): | ||||||
| ``` | ``` | ||||||
| Roses are red. Violets are blue. | Roses are red. Violets are blue. | ||||||
| Patch is quite hard. I cannot rhyme. | Patch is quite hard. I cannot rhyme. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Local changes (`my` file): | ##### Local changes (`my` file): | ||||||
| ``` | ``` | ||||||
| Roses are red. Violets are blue. | Roses are red. Violets are blue. | ||||||
| Patching is hard. I still cannot rhyme. | Patching is hard. I still cannot rhyme. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Remote changes (`your` file): | ##### Remote changes (`your` file): | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
|  | @ -43,18 +74,23 @@ Patch is quite hard. | ||||||
| I cannot do verses. | I cannot do verses. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Token-merged version with `werge merge my orig your` (conflicts on the space | ##### Token-merged version | ||||||
| change that is too close to the disappearing "still" token): | 
 | ||||||
|  | This is produced with `werge merge my old your` (conflicts on the space change | ||||||
|  | that is too close to the disappearing "still" token): | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
| Patching is hard.<<<<< I still||||| I===== | Patching is hard.<<<<< I still||||| I===== | ||||||
| I>>>>> cannot do verses. | I>>>>> cannot do verses. | ||||||
| ``` | ``` | ||||||
| (NOTE: option `-G` gives nicely colored output that is much easier to read.) | (NOTE: option `-G` gives nicely colored output that is much easier to read. | ||||||
|  | Alternatively you can install the syntax highlighting for `vim`.) | ||||||
| 
 | 
 | ||||||
| Token-merged version with separate space resolution using `-s` (conflicts get | ##### Merge with separate space resultion | ||||||
| fixed separately): | Adding option `-s` to `werge merge` causes it to resolve space conflicts | ||||||
|  | separately, usually helping many cases that would be easily resolvable by a | ||||||
|  | human: | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
|  | @ -62,7 +98,8 @@ Patching is hard. | ||||||
| I still cannot do verses. | I still cannot do verses. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| A harder-conflicting file (`theirs`): | ##### Mixing in unresolvable conflict | ||||||
|  | A harder-conflicting file (`their`): | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
|  | @ -70,7 +107,7 @@ Merging is quite hard. | ||||||
| I cannot do verses. | I cannot do verses. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| `werge merge mine orig theirs -s` highlights the actual unmergeable change: | `werge merge my old their -s` highlights the actual unmergeable change: | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
|  | @ -134,18 +171,9 @@ because the approach was too complex. Before that, the issue was tackled by | ||||||
| Arek Antoniewicz on MFF CUNI, who used regex-edged DFAs (REDFAs) to construct | Arek Antoniewicz on MFF CUNI, who used regex-edged DFAs (REDFAs) to construct | ||||||
| user-specifiable tokenizers in a pretty cool way. | user-specifiable tokenizers in a pretty cool way. | ||||||
| 
 | 
 | ||||||
| ## Installation | ## Integration with `git` | ||||||
| 
 | 
 | ||||||
| ```sh | ### Automerging conflicts | ||||||
| cabal install |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Running of `werge` requires a working installation of `diff` compatible |  | ||||||
| with the one from [GNU diffutils](https://www.gnu.org/software/diffutils/). You |  | ||||||
| may set up a path to such `diff` (or a wrapper script) via environment variable |  | ||||||
| `WERGE_DIFF`. |  | ||||||
| 
 |  | ||||||
| ## Use with `git` |  | ||||||
| 
 | 
 | ||||||
| `werge` can automatically process files that are marked in `git` as merge | `werge` can automatically process files that are marked in `git` as merge | ||||||
| conflicts: | conflicts: | ||||||
|  | @ -161,6 +189,85 @@ settings it runs `git add` on them. The current changes in the files are | ||||||
| replaced by the merged (or partially merged) state; backups are written | replaced by the merged (or partially merged) state; backups are written | ||||||
| automatically to `filename.werge-backup`. | automatically to `filename.werge-backup`. | ||||||
| 
 | 
 | ||||||
|  | Optionally, you can specify exact files to be automerged. That is useful for | ||||||
|  | cases when only some of the conflicting files should be processed by `werge`: | ||||||
|  | 
 | ||||||
|  | ```sh | ||||||
|  | $ werge git my/conflicting/file.txt | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Support for merging complex types of changes (deletes, directory moves, | ||||||
|  | symlinks, ...) via this interface is currently limited. `werge` can be used as | ||||||
|  | a mergetool or a merge driver to ameliorate that. | ||||||
|  | 
 | ||||||
|  | ### Use as `git difftool` and `git mergetool` | ||||||
|  | 
 | ||||||
|  | The `git` config below allows direct use of `werge` as `git difftool -t werge` | ||||||
|  | and `git mergetool -t werge`: | ||||||
|  | ```ini | ||||||
|  | [difftool "werge"] | ||||||
|  | 	cmd = werge diff -G $LOCAL $REMOTE | ||||||
|  | [mergetool "werge"] | ||||||
|  | 	cmd = werge merge $LOCAL $BASE $REMOTE > $MERGED | ||||||
|  | 	trustExitCode = true | ||||||
|  | 
 | ||||||
|  | # variant for separate resolution of space (solves more conflicts): | ||||||
|  | [mergetool "spacewerge"] | ||||||
|  | 	cmd = werge merge -s $LOCAL $BASE $REMOTE > $MERGED | ||||||
|  | 	trustExitCode = true | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | One issue with `git` mergetools is that they are supposed to be interactive, | ||||||
|  | and thus `git` expects them to always produce a completely merged, conflictless | ||||||
|  | result. In turn, if the auto-merging with `git mergetool -t werge` fails with | ||||||
|  | conflicts, `git` assumes a complete failure and restores the original version | ||||||
|  | from the backup. To enable a more useful behavior, use `werge` as a merge | ||||||
|  | driver (see below). | ||||||
|  | 
 | ||||||
|  | ### Use as a `git` merge driver | ||||||
|  | 
 | ||||||
|  | Add this to your git config: | ||||||
|  | ```ini | ||||||
|  | [merge "werge"] | ||||||
|  | 	name = werge | ||||||
|  | 	driver = werge merge %A %O %B > %P | ||||||
|  | 	recursive = binary | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Then, specify that the "werge" driver should be used for certain files in your | ||||||
|  | repository's `.gitattributes`: | ||||||
|  | ``` | ||||||
|  | *.md merge=werge | ||||||
|  | *.tex merge=werge | ||||||
|  | # ... etc | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | With this in place, `git merge` will automatically run `werge` to merge the | ||||||
|  | marked files in the repository. On conflict, you will have the files marked | ||||||
|  | with the usual (werge's usual) conflict markers, and you will be able to | ||||||
|  | resolve them just as with the normal merging workflow. | ||||||
|  | 
 | ||||||
|  | **Hint:** As with `spacewerge` mergetool above, it is beneficial to add a few | ||||||
|  | conflict-resolving options such as `-s` to the `driver`, in order to help the | ||||||
|  | automerges pass nicely. | ||||||
|  | 
 | ||||||
|  | ### Use with `git rebase` | ||||||
|  | 
 | ||||||
|  | The merge driver and mergetools as configured above will also automatically | ||||||
|  | work with `git rebase` that runs in the "merge mode" (which is the default). | ||||||
|  | 
 | ||||||
|  | As a possible source of confusion, the "my" and "your" versions are somewhat swapped (as implied by semantics): | ||||||
|  | 
 | ||||||
|  | - With `git checkout mybranch; git merge otherbranch`, the conflicts will look | ||||||
|  |   roughly like this: | ||||||
|  |   ``` | ||||||
|  |   <<<<< mybranch version ||||| merge base ===== otherbranch version >>>>> | ||||||
|  |   ``` | ||||||
|  | - With `git checkout mybranch; git rebase otherbranch`, the logic is reversed: | ||||||
|  |   ``` | ||||||
|  |   <<<<< otherbranch version ||||| common base ===== mybranch version >>>>> | ||||||
|  |   ``` | ||||||
|  | 
 | ||||||
| ## Current `--help` and features | ## Current `--help` and features | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								vim/werge.vim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vim/werge.vim
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | " Vim syntax file | ||||||
|  | " Language: werge | ||||||
|  | " Maintainer: Mirek Kratochvil | ||||||
|  | " Last Change: Oct 14, 2025 | ||||||
|  | " Version: 1 | ||||||
|  | " URL: https://github.com/exaexa/werge | ||||||
|  | 
 | ||||||
|  | " quit if a syntax file was already loaded | ||||||
|  | if exists("b:current_syntax") | ||||||
|  |   finish | ||||||
|  | endif | ||||||
|  | 
 | ||||||
|  | " syntax for the werge files | ||||||
|  | syntax region wergeHunk start=/<<<<</ end=/>>>>>/ contains=wergeRm,wergeDiffAdd,wergeConflictOrigAdd | ||||||
|  | syntax region wergeRm  start=/<<<<</hs=e+1  end=/|||||/he=s-1,me=s-1 contained | ||||||
|  | syntax match wergeDiffAdd /|||||\(\_[^>=]\|>\{1,4\}>\@!\|=\{1,4\}=\@!\)*>>>>>/ms=s+5,me=e-5 contained | ||||||
|  | syntax match wergeConflictOrigAdd /|||||\(\_[^=>]\|=\{1,4\}=\@!\|>\{1,4\}>\@!\)*=====\(\_[^=>]\|=\{1,4\}=\@!\|>\{1,4\}>\@!\)*>>>>>/me=e-5 contained contains=wergeConflictOrig,wergeconflictAdd | ||||||
|  | syntax region wergeConflictOrig start=/|||||/hs=e+1  end=/=====/he=s-1,me=s-1 contained | ||||||
|  | syntax region wergeConflictAdd start=/=====/hs=e+1  end=/>>>>>/he=s-1,me=s-1 contained | ||||||
|  | 
 | ||||||
|  | " color specification | ||||||
|  | highlight default link wergeHunk Comment | ||||||
|  | highlight default link wergeRm Removed | ||||||
|  | highlight default link wergeDiffAdd Added | ||||||
|  | highlight default link wergeConflictOrigAdd Comment | ||||||
|  | highlight default link wergeConflictOrig Changed | ||||||
|  | highlight default link wergeConflictAdd Added | ||||||
|  | 
 | ||||||
|  | let b:current_syntax = "werge" | ||||||
|  | @ -1,16 +1,17 @@ | ||||||
| cabal-version:   3.0 | cabal-version:   3.0 | ||||||
| name:            werge | name:            werge | ||||||
| version:         0.2.0.0 | version:         0.2.1.0 | ||||||
| synopsis:        mergetool for mangled-up bite-size changes | synopsis:        mergetool for mangled-up bite-size changes | ||||||
| license:         GPL-3.0-or-later | license:         GPL-3.0-or-later | ||||||
| license-file:    LICENSE | license-file:    LICENSE | ||||||
|  | copyright:       (c) 2025 Mirek Kratochvil | ||||||
| author:          Mirek Kratochvil | author:          Mirek Kratochvil | ||||||
| maintainer:      exa.exa@gmail.com | maintainer:      exa.exa@gmail.com | ||||||
| 
 | 
 | ||||||
| -- copyright: | -- copyright: | ||||||
| category:        Text | category:        Text | ||||||
| build-type:      Simple | build-type:      Simple | ||||||
| extra-doc-files: CHANGELOG.md | extra-doc-files: README.md vim/werge.vim | ||||||
| 
 | 
 | ||||||
| -- extra-source-files: | -- extra-source-files: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue