本文介绍了.PO(gettext)文件的3路Git合并驱动程序在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我已经有了下面的 [attr] POFILE merge = merge-po-files locale / *。po POFILE 位于 .gitattributes 并且我希望合并分支以在paraller分支中修改相同的本地化文件(例如 locale / en.po )时正确工作。我正在使用以下合并驱动程序: #!/ bin / bash #git合并驱动程序.PO文件(gettext本地化)#安装:#git config merge.merge-po-files.driver./bin/merge-po-files%A%O%B LOCAL =$ {1} ._ LOCAL_ BASE =$ {2} ._ BASE_ REMOTE =$ {3} ._ REMOTE_ #重命名为更有意义的文件名以获得更好的冲突结果 cp$ {1}$ LOCAL cp$ {2}$ BASE cp$ {3 }$ REMOTE #合并文件并用结果覆盖本地文件 msgcat$ LOCAL$ BASE$ REMOTE-o$ {1}| |退出1 #清除 rm -f$ LOCAL$ BASE$ REMOTE #检查合并是否有冲突 fgrep -q'# - # - # - # - #'$ {1}&&出口1 #如果我们到达这里,合并成功出口0 然而, msgcat 太笨了,这不是真正的三路合并。 例如,如果我有 BASE版本 $ msgidfoo msgstrfoo li> 本地版本 msgidfoo msgstrbar REMOTE版本 msgidfoo msgstrfoo 我最终会遇到冲突。 然而,真正的三路合并驱动程序会输出正确的合并: msgid foo msgstrbar 请注意,我不能简单地添加 - use-first 到 msgcat ,因为REMOTE可能包含更新的翻译。另外,如果BASE,LOCAL和REMOTE都是唯一的,我仍然需要冲突,因为那实际上是冲突。 我需要什么如果可能的话,改变以使之有效吗?奖励分数小于'# - # - # - # - #'的疯狂冲突标记。 解决方案从Mikko的回答中获得一些启发,我们已经为 git-whistles Ruby宝石。 它不依赖 git-merge 或者用Perl重写字符串,并且只使用Gettext工具操纵PO文件。 这里是代码): $ b #!/ bin / sh ##PO文件的三路合并驱动程序# set -e #失败处理程序 on_error(){本地parent_lineno =$ 1本地消息=$ 2 local code =$ {3:-1} if [[-n$ message]];然后回声在$ {parent_lineno}:$ {message}上出现错误;以状态$ {code}退出 else echo在$ {parent_lineno}或其附近出错;退出状态$ {code} fi exit 255 } trap'on_error $ {LINENO}'ERR #给出一个文件,找到匹配其内容的路径 show_file(){ hash =`git hash-object$ {1}` git ls-tree -r HEAD | fgrep$ hash| cut -b54- } #使用默认选项包装msgmerge 函数m_msgmerge(){ msgmerge --force-po --quiet --no-fuzzy - 匹配$ @ } #使用默认选项包装msgcat 函数m_msgcat(){ msgcat --force-po $ @ } #从输入中删除墓地字符串strip_graveyard(){ sed -e'/ ^#〜/ d'} #选择具有冲突标记的消息#传递-v到反向选择函数grep_conflicts(){ msggrep $ @ --msgstr -F -e' # - # - #' - } #从$ 1中选择也在$ 2中但其内容已更改的消息 function extract_changes(){ msgcat - o - $ 1 $ 2 \ | grep_conflicts \ | m_msgmerge -o - $ 1 - \ | strip_graveyard } BASE = $ 1 LOCAL = $ 2 REMOTE = $ 3 OUTPUT = $ LOCAL TEMP =` mktemp / tmp / merge-po.XXXX` echo使用自定义PO合并驱动程序(`show_file $ {LOCAL}`; $ TEMP) #提取PO来自当前分支的头(文件顶部,直到第一个空行) sed -e'/ ^ $ / q'< $ LOCAL> $ {TEMP} .header #clean输入文件 msguniq --force-po -o $ {TEMP} .base --unique $ {BASE} msguniq - force-po -o $ {TEMP} .local --unique $ {LOCAL} msguniq --force-po -o $ {TEMP} .remote --unique $ {REMOTE} $ b $在本地上更改b#消息extract_changes $ {TEMP} .local $ {TEMP} .base> $ {TEMP} .local-changes #在远程上更改的消息extract_changes $ {TEMP} .remote $ {TEMP} .base> $ {TEMP} .remote-changes #不变消息 m_msgcat -o - $ {TEMP} .base $ {TEMP} .local $ {TEMP} .remote \ | grep_conflicts -v \ > $ {TEMP} .unchanged #在本地和远程(冲突)上已更改的消息 m_msgcat -o - $ {TEMP} .remote-changes $ {TEMP} .local-changes \\ \\ | grep_conflicts \ > $ {TEMP} .conflicts #消息在本地更改,不在远程;反之亦然 m_msgcat -o $ {TEMP} .local-only --unique $ {TEMP} .local-changes $ {TEMP} .conflicts m_msgcat -o $ {TEMP} .remote-只有--unique $ {TEMP} .remote-changes $ {TEMP} .conflicts #大合并 m_msgcat -o $ {TEMP} .merge1 $ {TEMP} .unchanged $ {TEMP} .conflicts $ {TEMP} .local-only $ {TEMP} .remote-only #创建一个模板来过滤实际需要的消息(本地和远程消息) m_msgcat -o - $ {TEMP} .local $ {TEMP} .remote \ | m_msgmerge -o $ {TEMP} .merge2 $ {TEMP} .merge1 - #最终合并,添加保存的头文件 m_msgcat -o $ {TEMP} .merge3 --use-first $ {TEMP} .header $ {TEMP} .merge2 #产生输出文件(覆盖输入LOCAL文件) cat $ {TEMP} .merge3> $ OUTPUT #检查冲突 if grep'# - #'$ OUTPUT> / dev / null;然后 echo在$ {TEMP} .local和$ {TEMP} .remote之间检测到冲突 echo出口1 fi rm -f $ {TEMP} * 出口0 I already have following[attr]POFILE merge=merge-po-fileslocale/*.po POFILEin the .gitattributes and I'd like to get merging of branches to work correctly when the same localization file (e.g. locale/en.po) has been modified in paraller branches. I'm currently using following merge driver:#!/bin/bash# git merge driver for .PO files (gettext localizations)# Install:# git config merge.merge-po-files.driver "./bin/merge-po-files %A %O %B"LOCAL="${1}._LOCAL_"BASE="${2}._BASE_"REMOTE="${3}._REMOTE_"# rename to bit more meaningful filenames to get better conflict resultscp "${1}" "$LOCAL"cp "${2}" "$BASE"cp "${3}" "$REMOTE"# merge files and overwrite local file with the resultmsgcat "$LOCAL" "$BASE" "$REMOTE" -o "${1}" || exit 1# cleanuprm -f "$LOCAL" "$BASE" "$REMOTE"# check if merge has conflictsfgrep -q '#-#-#-#-#' "${1}" && exit 1# if we get here, merge is successfulexit 0However, the msgcat is too dumb and this is not a true three way merge.For example, if I haveBASE versionmsgid "foo"msgstr "foo"LOCAL versionmsgid "foo"msgstr "bar"REMOTE versionmsgid "foo"msgstr "foo"I'll end up with a conflict.However, a true three way merge driver would output correct merge:msgid "foo"msgstr "bar"Note that I cannot simply add --use-first to msgcat because the REMOTE could contain the updated translation. In addition, if BASE, LOCAL and REMOTE are all unique, I still want a conflict, because that would really be a conflict.What do I need to change to make this work? Bonus points for less insane conflict marker than '#-#-#-#-#', if possible. 解决方案 Taking some inspiration from Mikko's answer, we've added a full-fledged 3-way merger to the git-whistles Ruby gem.It doesn't rely of git-merge or rewriting string with Perl, and only manipulates PO files with Gettext tools.Here's the code (MIT licensed):#!/bin/sh## Three-way merge driver for PO files#set -e# failure handleron_error() { local parent_lineno="$1" local message="$2" local code="${3:-1}" if [[ -n "$message" ]] ; then echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}" else echo "Error on or near line ${parent_lineno}; exiting with status ${code}" fi exit 255}trap 'on_error ${LINENO}' ERR# given a file, find the path that matches its contentsshow_file() { hash=`git hash-object "${1}"` git ls-tree -r HEAD | fgrep "$hash" | cut -b54-}# wraps msgmerge with default optionsfunction m_msgmerge() { msgmerge --force-po --quiet --no-fuzzy-matching $@}# wraps msgcat with default optionsfunction m_msgcat() { msgcat --force-po $@}# removes the "graveyard strings" from the inputfunction strip_graveyard() { sed -e '/^#~/d'}# select messages with a conflict marker# pass -v to inverse selectionfunction grep_conflicts() { msggrep $@ --msgstr -F -e '#-#-#' -}# select messages from $1 that are also in $2 but whose contents have changedfunction extract_changes() { msgcat -o - $1 $2 \ | grep_conflicts \ | m_msgmerge -o - $1 - \ | strip_graveyard}BASE=$1LOCAL=$2REMOTE=$3OUTPUT=$LOCALTEMP=`mktemp /tmp/merge-po.XXXX`echo "Using custom PO merge driver (`show_file ${LOCAL}`; $TEMP)"# Extract the PO header from the current branch (top of file until first empty line)sed -e '/^$/q' < $LOCAL > ${TEMP}.header# clean input filesmsguniq --force-po -o ${TEMP}.base --unique ${BASE}msguniq --force-po -o ${TEMP}.local --unique ${LOCAL}msguniq --force-po -o ${TEMP}.remote --unique ${REMOTE}# messages changed on localextract_changes ${TEMP}.local ${TEMP}.base > ${TEMP}.local-changes# messages changed on remoteextract_changes ${TEMP}.remote ${TEMP}.base > ${TEMP}.remote-changes# unchanged messagesm_msgcat -o - ${TEMP}.base ${TEMP}.local ${TEMP}.remote \ | grep_conflicts -v \ > ${TEMP}.unchanged# messages changed on both local and remote (conflicts)m_msgcat -o - ${TEMP}.remote-changes ${TEMP}.local-changes \ | grep_conflicts \ > ${TEMP}.conflicts# messages changed on local, not on remote; and vice-versam_msgcat -o ${TEMP}.local-only --unique ${TEMP}.local-changes ${TEMP}.conflictsm_msgcat -o ${TEMP}.remote-only --unique ${TEMP}.remote-changes ${TEMP}.conflicts# the big mergem_msgcat -o ${TEMP}.merge1 ${TEMP}.unchanged ${TEMP}.conflicts ${TEMP}.local-only ${TEMP}.remote-only# create a template to filter messages actually needed (those on local and remote)m_msgcat -o - ${TEMP}.local ${TEMP}.remote \ | m_msgmerge -o ${TEMP}.merge2 ${TEMP}.merge1 -# final merge, adds saved headerm_msgcat -o ${TEMP}.merge3 --use-first ${TEMP}.header ${TEMP}.merge2# produce output file (overwrites input LOCAL file)cat ${TEMP}.merge3 > $OUTPUT# check for conflictsif grep '#-#' $OUTPUT > /dev/null ; then echo "Conflict(s) detected" echo " between ${TEMP}.local and ${TEMP}.remote" exit 1firm -f ${TEMP}*exit 0 这篇关于.PO(gettext)文件的3路Git合并驱动程序在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-04 17:25