Skip to content

Instantly share code, notes, and snippets.

@mezis
Last active March 11, 2021 08:37
  • Star 38 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
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

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