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: | ||||
|         os: [ubuntu-22.04, macos-15] | ||||
|         ghc: | ||||
|           - "9.6" | ||||
|           - "9.12" | ||||
|     steps: | ||||
|       - 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) | ||||
|     bad e = do | ||||
|       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 | ||||
| --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 | ||||
| 
 | ||||
| Original (`old` file): | ||||
| ##### Original (`old` file): | ||||
| ``` | ||||
| Roses are red. Violets are blue. | ||||
| Patch is quite hard. I cannot rhyme. | ||||
| ``` | ||||
| 
 | ||||
| Local changes (`my` file): | ||||
| ##### Local changes (`my` file): | ||||
| ``` | ||||
| Roses are red. Violets are blue. | ||||
| Patching is hard. I still cannot rhyme. | ||||
| ``` | ||||
| 
 | ||||
| Remote changes (`your` file): | ||||
| ##### Remote changes (`your` file): | ||||
| ``` | ||||
| Roses are red. | ||||
| Violets are blue. | ||||
|  | @ -43,18 +74,23 @@ Patch is quite hard. | |||
| I cannot do verses. | ||||
| ``` | ||||
| 
 | ||||
| Token-merged version with `werge merge my orig your` (conflicts on the space | ||||
| change that is too close to the disappearing "still" token): | ||||
| ##### Token-merged version | ||||
| 
 | ||||
| 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. | ||||
| Violets are blue. | ||||
| Patching is hard.<<<<< I still||||| I===== | ||||
| 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 | ||||
| fixed separately): | ||||
| ##### Merge with separate space resultion | ||||
| 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. | ||||
| Violets are blue. | ||||
|  | @ -62,7 +98,8 @@ Patching is hard. | |||
| I still cannot do verses. | ||||
| ``` | ||||
| 
 | ||||
| A harder-conflicting file (`theirs`): | ||||
| ##### Mixing in unresolvable conflict | ||||
| A harder-conflicting file (`their`): | ||||
| ``` | ||||
| Roses are red. | ||||
| Violets are blue. | ||||
|  | @ -70,7 +107,7 @@ Merging is quite hard. | |||
| 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. | ||||
| 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 | ||||
| user-specifiable tokenizers in a pretty cool way. | ||||
| 
 | ||||
| ## Installation | ||||
| ## Integration with `git` | ||||
| 
 | ||||
| ```sh | ||||
| 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` | ||||
| ### Automerging conflicts | ||||
| 
 | ||||
| `werge` can automatically process files that are marked in `git` as merge | ||||
| 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 | ||||
| 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 | ||||
| 
 | ||||
| ``` | ||||
|  |  | |||
							
								
								
									
										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 | ||||
| name:            werge | ||||
| version:         0.2.0.0 | ||||
| version:         0.2.1.0 | ||||
| synopsis:        mergetool for mangled-up bite-size changes | ||||
| license:         GPL-3.0-or-later | ||||
| license-file:    LICENSE | ||||
| copyright:       (c) 2025 Mirek Kratochvil | ||||
| author:          Mirek Kratochvil | ||||
| maintainer:      exa.exa@gmail.com | ||||
| 
 | ||||
| -- copyright: | ||||
| category:        Text | ||||
| build-type:      Simple | ||||
| extra-doc-files: CHANGELOG.md | ||||
| extra-doc-files: README.md vim/werge.vim | ||||
| 
 | ||||
| -- extra-source-files: | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue