Skip to content

Instantly share code, notes, and snippets.

@mezis
Last active November 20, 2023 11:33
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mezis/1605647 to your computer and use it in GitHub Desktop.
Save mezis/1605647 to your computer and use it in GitHub Desktop.
Git merge driver for PO files
#!/bin/sh
#
# *******************************************
# WARNING: this does *not* handle 3-way merges properly.
# Anything modified on the local branch since the common base will get ignored.
#
# FOR ANYONE LANDING HERE:
# This script is now updated as part of the git-whistles gem.
# https://github.com/mezis/git-whistles
# *******************************************
#
# Custom Git merge driver - merges PO files using msgcat(1)
#
# - Install gettext
#
# - Place this script in your PATH
#
# - Add this to your .git/config :
#
# [merge "pofile"]
# name = Gettext merge driver
# driver = git merge-po %O %A %B
#
# - Add this to .gitattributes :
#
# *.po merge=pofile
# *.pot merge=pofile
#
# - When merging branches, conflicts in PO files will be maked with "#-#-#-#"
#
O=$1
A=$2
B=$3
# Extract the PO header from the current branch (top of file until first empty line)
header=$(mktemp /tmp/merge-po.XXXX)
sed -e '/^$/q' < $A > $header
# Merge files, then repair header
temp=$(mktemp /tmp/merge-po.XXXX)
msgcat -o $temp $A $B
msgcat --use-first -o $A $header $temp
# Clean up
rm $header $temp
# Check for conflicts
conflicts=$(grep -c "#-#" $A)
test $conflicts -gt 0 && exit 1
exit 0
@pusewicz
Copy link

Very cool.

@mezis
Copy link
Author

mezis commented Jan 13, 2012

Thanks Pete. This will save us an awful lot of time ;)

@cormier
Copy link

cormier commented Jul 10, 2012

Thank you very much, this is very useful!

@alfor
Copy link

alfor commented Aug 10, 2012

I had a problem to set it up because of the name of the file, it must be named 'git-merge-po' without the '.sh' for this solution to work.
I didn't know that git rename application to command: git-merge-po become the command git merge-po, nifty.

Thanks you very much for this solutions !

@mikkorantalainen
Copy link

@dbolser-ebi
Copy link

What is a po files?

@mikkorantalainen
Copy link

dbolser-ebi: I don't know how you hit this page without knowing what is a PO file.

A .po file is used as a source for GNU gettext tools. It's usually converted to .mo file format with command msgfmt which is also part of gettext. A .po file looks a lot like a normal text file but it really is a database format for gettext localizations. And if you allow normal git merge driver to do the merge as if the file was a normal text file, you'll end up with a corrupted .po file. The gettext does include a command called msgmerge but despite its name, it is not suitable for merging different versions of localizations.

There was a pull request to add msg3way to gettext around 4 years ago (http://lists.gnu.org/archive/html/bug-gnu-utils/2010-11/msg00051.html) but it never got any traction.

@mplewis
Copy link

mplewis commented Mar 27, 2015

@mikkorantalainen: I found this page by searching on how to build a custom git merge strategy. This is one of the only examples that shows how you can build one and integrate it into your project.

@mezis
Copy link
Author

mezis commented Apr 9, 2015

For anyone still interested, git-whistles is getting a proper 3-way PO merger. Doesn't rely on Perl and string wrangling line the SO suggestions pointed to by @mikkorantalainen (which were a great source of inspiration).

mezis/git-whistles#39

@mikkorantalainen
Copy link

Here's a link to 3-way merge for PO files that I currently use: https://stackoverflow.com/a/68799310/334451
It has some ideas from my older driver and some ideas that @mezis used and I partially re-wrote it to run on multiple CPU cores as much as possible. I've been using it for a couple of years without any invalid merges so I consider that the best solution until gettext includes proper 3-way merge one day.

@dbolser
Copy link

dbolser commented Nov 20, 2023

@mikkorantalainen: I found this page by searching on how to build a custom git merge strategy. This is one of the only examples that shows how you can build one and integrate it into your project.

me too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment