Compare commits
	
		
			No commits in common. "f294df0e69fce805ba38641f3b730461fee91e3b" and "aea372a87dd8c10d2e8604b4d0ea81391c11f548" have entirely different histories.
		
	
	
		
			f294df0e69
			...
			aea372a87d
		
	
		
							
								
								
									
										1
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -14,6 +14,7 @@ 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 | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | # 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 129) |       exitWith (ExitFailure 2) | ||||||
|  |  | ||||||
							
								
								
									
										149
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								README.md
									
									
									
									
									
								
							|  | @ -21,52 +21,21 @@ 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. | ||||||
|  | @ -74,23 +43,18 @@ Patch is quite hard. | ||||||
| I cannot do verses. | I cannot do verses. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ##### Token-merged version | Token-merged version with `werge merge my orig your` (conflicts on the space | ||||||
| 
 | 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`.) |  | ||||||
| 
 | 
 | ||||||
| ##### Merge with separate space resultion | Token-merged version with separate space resolution using `-s` (conflicts get | ||||||
| Adding option `-s` to `werge merge` causes it to resolve space conflicts | fixed separately): | ||||||
| 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. | ||||||
|  | @ -98,8 +62,7 @@ Patching is hard. | ||||||
| I still cannot do verses. | I still cannot do verses. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ##### Mixing in unresolvable conflict | A harder-conflicting file (`theirs`): | ||||||
| A harder-conflicting file (`their`): |  | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
|  | @ -107,7 +70,7 @@ Merging is quite hard. | ||||||
| I cannot do verses. | I cannot do verses. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| `werge merge my old their -s` highlights the actual unmergeable change: | `werge merge mine orig theirs -s` highlights the actual unmergeable change: | ||||||
| ``` | ``` | ||||||
| Roses are red. | Roses are red. | ||||||
| Violets are blue. | Violets are blue. | ||||||
|  | @ -171,9 +134,18 @@ 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. | ||||||
| 
 | 
 | ||||||
| ## Integration with `git` | ## Installation | ||||||
| 
 | 
 | ||||||
| ### Automerging conflicts | ```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` | ||||||
| 
 | 
 | ||||||
| `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: | ||||||
|  | @ -189,85 +161,6 @@ 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 | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | @ -1,29 +0,0 @@ | ||||||
| " 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,17 +1,16 @@ | ||||||
| cabal-version:   3.0 | cabal-version:   3.0 | ||||||
| name:            werge | name:            werge | ||||||
| version:         0.2.1.0 | version:         0.2.0.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: README.md vim/werge.vim | extra-doc-files: CHANGELOG.md | ||||||
| 
 | 
 | ||||||
| -- extra-source-files: | -- extra-source-files: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue