当前位置:  开发笔记 > 编程语言 > 正文

我怎么告诉git总是选择我的本地版本来解决特定文件上的冲突合并?

如何解决《我怎么告诉git总是选择我的本地版本来解决特定文件上的冲突合并?》经验,为你挑选了1个好方法。

假设我通过git存储库与某人合作,并且有一个特定的文件,我永远不想接受任何外部更改.

有没有办法让我设置我的本地仓库,以便每当我拉动时不抱怨冲突的合并?我想在合并此文件时始终选择我的本地版本.



1> VonC..:

在配置文件的特定实例上,我同意Ron的回答:
配置应该对您的工作区是"私有的"(因此"忽略",如"在.gitignore文件中声明").
您可能有一个带有标记化值的配置文件模板,以及一个将该文件转换为私有(并忽略)配置文件的脚本.config.template


但是,这个具体的评论并没有回答更广泛的更普遍的问题,即你的问题(!):

我怎么告诉git总是选择我的本地版本来解决特定文件上的冲突合并?(对于任何文件或文件组)

这种合并是一种"复制合并",在发生冲突时,您将始终复制文件的"我们的"或"他们的"版本.

(正如Brian Vandenberg 在评论中指出的那样,' ours和' theirs'在这里被用于合并.
它们被反转为一个rebase:参见" Why is the meaning of “ours” and “theirs” reversed with git-svn",它使用了一个rebase," git rebase,跟踪'本地'和'远程' " )

对于"一个文件"(一般来说,不是说"配置"文件,因为它是一个不好的例子),你可以通过合并调用自定义脚本来实现.
Git将调用该脚本,因为您将定义一个gitattributes值,该值定义自定义合并驱动程序.

在这种情况下,"自定义合并驱动程序"是一个非常简单的脚本,它基本上将保持当前版本不变,因此允许您始终选择本地版本.


让我们在一个简单的场景中测试,在Windows上使用msysgit 1.6.3,在一个简单的DOS会话中:

cd f:\prog\git\test
mkdir copyMerge\dirWithConflicts
mkdir copyMerge\dirWithCopyMerge
cd copyMerge
git init
Initialized empty Git repository in F:/prog/git/test/copyMerge/.git/

现在,让我们制作两个文件,这两个文件都会有冲突,但会以不同的方式合并.

echo a > dirWithConflicts\a.txt
echo b > dirWithCopyMerge\b.txt
git add -A
git commit -m "first commit with 2 directories and 2 files"
[master (root-commit) 0adaf8e] first commit with 2 directories and 2 files

我们将在两个不同的git分支中的这两个文件的内容中引入"冲突":

git checkout -b myBranch
Switched to a new branch 'myBranch'
echo myLineForA >> dirWithConflicts\a.txt
echo myLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in myBranch"
[myBranch 97eac61] add modification in myBranch

git checkout master
Switched to branch 'master'
git checkout -b hisBranch
Switched to a new branch 'hisBranch'
echo hisLineForA >> dirWithConflicts\a.txt
echo hisLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in hisBranch"
[hisBranch 658c31c] add modification in hisBranch

现在,让我们尝试将"hisBranch"合并到"myBranch"上,并:

冲突合并的手动解决方案

除了dirWithCopyMerge\b.txt在那里我总是想保持我的版本b.txt.

由于合并发生在' MyBranch',我们将切换回它,并添加' gitattributes'指令,它将自定义合并行为.

git checkout myBranch
Switched to branch 'myBranch'
echo b.txt merge=keepMine > dirWithCopyMerge\.gitattributes
git config merge.keepMine.name "always keep mine during merge"
git config merge.keepMine.driver "keepMine.sh %O %A %B"
git add -A
git commit -m "prepare myBranch with .gitattributes merge strategy"
[myBranch ec202aa] prepare myBranch with .gitattributes merge strategy

我们.gitattributesdirWithCopyMerge目录中定义了一个文件(仅在发生合并的分支中定义:) myBranch,我们有一个.git\config文件,现在包含一个合并驱动程序.

[merge "keepMine"]
        name = always keep mine during merge
        driver = keepMine.sh %O %A %B

如果你还没有定义keepMine.sh,并且无论如何都要启动合并,这就是你得到的.

git merge hisBranch
sh: keepMine.sh: command not found
fatal: Failed to execute internal merge
git st
# On branch myBranch
# Changed but not updated:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#       modified:   dirWithConflicts/a.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

type dirWithConflicts\a.txt
a
<<<<<<< HEAD:dirWithConflicts/a.txt
myLineForA
=======
hisLineForA
>>>>>>> hisBranch:dirWithConflicts/a.txt

那样就好:

a.txt 准备合并,并在其中发生冲突

b.txt仍然没有被触及,因为合并驱动程序应该处理它(由于.gitattributes其目录中的文件中的指令).

keepMine.sh在你的%PATH%(或$PATH我们的Unix朋友)中定义一个位置.我当然都这样做:我在VirtualBox会话中有一个Ubuntu会话)

作为评论的lrkwz,而"中描述的合并策略的"节自定义的Git - Git属性,你可以替换的shell命令shell脚本true.

git config merge.keepMine.driver true

但在一般情况下,您可以定义脚本文件:

keepMine.sh

# I want to keep MY version when there is a conflict
# Nothing to do: %A (the second parameter) already contains my version
# Just indicate the merge has been successfully "resolved" with the exit status
exit 0

(这是一个简单的合并驱动程序;)(在这种情况下甚至更简单,使用true)
(如果你想保留另一个版本,只需exit 0在行之前添加:
cp -f $3 $2.
就是这样.你合并驱动程序将远离其他版本分支,覆盖任何本地更改)

现在,让我们从头开始重试合并:

git reset --hard
HEAD is now at ec202aa prepare myBranch with .gitattributes merge strategy

git merge hisBranch
Auto-merging dirWithConflicts/a.txt
CONFLICT (content): Merge conflict in dirWithConflicts/a.txt
Auto-merging dirWithCopyMerge/b.txt
Automatic merge failed; fix conflicts and then commit the result.

合并失败... 仅适用于a.txt.
编辑a.txt并从'hisBranch'中保留该行,然后:

git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version

让我们检查一下这个合并期间是否保留了b.txt

type dirWithCopyMerge\b.txt
b
myLineForB

最后一次提交确实代表完全合并:

git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.

(从Merge开始的行证明了这一点)


考虑你可以定义,组合和/或覆盖合并驱动程序,因为Git将:

检查

/.gitattributes(与相关路径位于同一目录中):将.gitattributes在目录中占优势

然后检查.gitattributes(在父目录中),只设置指令(如果尚未设置)

最后它检查$GIT_DIR/info/attributes.此文件用于覆盖树内设置.它将覆盖

/.gitattributes指令.

通过"组合",我的意思是"聚合"多个合并驱动程序.
Nick Green 在评论中尝试实际组合合并驱动程序:请参阅" 通过python git驱动程序合并pom ".
但是,正如他在另一个问题中所提到的,它只适用于冲突(两个分支中的并发修改).


应该引用`cp -f $ 3 $ 2`,即`cp -f"$ 3""$ 2"`.
@VonC谢谢.还有一个问题.在某些情况下(如果没有对正在合并的本地分支进行任何更改),似乎永远不会调用合并驱动程序,这会导致本地文件被修改(应该使用自定义合并驱动程序)防止它们在合并期间发生变化).有没有办法**强制**git始终使用合并驱动程序?
@ulmangt:你可以将这个脚本存储在git repo中,...只要你找到一种方法将其父目录添加到`PATH`(Unix或Windows`PATH`).由于该脚本将通过Unix bash shell或通过MingWin bash MsysGit Windows shell进行解释,因此它将是可移植的.
推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有