我该如何告诉git总是选择我的本地版本来处理特定文件上的冲突合并?

假设我正在通过git存储库与某人进行协作,并且有一个特定的文件我从不想接受任何外部更改。

有没有什么办法可以让我设置本地回购库,让我在每次合并时都不抱怨冲突的合并? 我想在合并这个文件时总是选择我的本地版本。


在配置文件的具体实例中,我会同意Ron的回答:
一个配置应该对你的工作空间“私有”(因此“忽略”,如在“ .gitignore文件中声明的”)。
你可能有一个带有标记值的配置文件模板,还有一个将该config.template文件转换为私有(并且被忽略)配置文件的脚本。


然而,这个具体的评论并没有回答什么是更广泛的更一般的问题,即你的问题(!):

我该如何告诉git总是选择我的本地版本来处理特定文件上的冲突合并? (用于任何文件或文件组)

这种合并是一种“复制合并”,当出现冲突时,您将始终复制文件的“我们的”或“他们的”版本。

(正如Brian Vandenberg在评论中指出的那样, ours ”和“ theirs ”在这里用于合并
他们被逆转为rebase :请参阅“ Why is the meaning of “ours” and “theirs” reversed with git-svn ”使用“rebit”,“ git rebase ,跟踪'local'和'remote'”来Why is the meaning of “ours” and “theirs” reversed with git-svn

对于“一个文件”(一般而言,不是说“config”文件,因为它是一个不好的例子),你可以通过一个通过合并调用的自定义脚本来实现。
Git会调用该脚本,因为您将定义一个gitattributes值,该值定义了一个自定义合并驱动程序

在这种情况下,“自定义合并驱动程序”是一个非常简单的脚本,基本上将保持当前版本不变,因此可以随时选择本地版本。


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

cd f:proggittest
mkdir copyMergedirWithConflicts
mkdir copyMergedirWithCopyMerge
cd copyMerge
git init
Initialized empty Git repository in F:/prog/git/test/copyMerge/.git/

现在,让我们创建两个文件,这两个文件都会有冲突,但会以不同方式合并。

echo a > dirWithConflictsa.txt
echo b > dirWithCopyMergeb.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 >> dirWithConflictsa.txt
echo myLineForB >> dirWithCopyMergeb.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 >> dirWithConflictsa.txt
echo hisLineForB >> dirWithCopyMergeb.txt
git add -A
git commit -m "add modification in hisBranch"
[hisBranch 658c31c] add modification in hisBranch

现在,让我们尝试将“myBranch”合并到“myBranch”中,然后:

  • 手动解决冲突合并
  • 除了dirWithCopyMergeb.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
    

    我们在dirWithCopyMerge目录中定义了一个.gitattributes文件(仅在要发生合并的分支中定义: myBranch ),并且我们有一个.gitconfig文件,该文件现在包含合并驱动程序。

    [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 <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #       modified:   dirWithConflicts/a.txt
    #
    no changes added to commit (use "git add" and/or "git commit -a")
    
    type dirWithConflictsa.txt
    a
    <<<<<<< HEAD:dirWithConflicts/a.txt
    myLineForA
    =======
    hisLineForA
    >>>>>>> hisBranch:dirWithConflicts/a.txt
    

    没事儿:

  • a.txt已经准备好被合并并且有冲突
  • b.txt仍然未被触动,因为合并驱动程序应该处理它(由于其目录中的.gitattributes文件中的指令)。
  • 在你的%PATH% (或者我们的Unix朋友的$PATH任何地方定义一个keepMine.sh ,当然我都这么做:我在一个VirtualBox会话中有一个Ubuntu会话)

    正如lrkwz所述,并在Customizing Git-Git Attributes的“Merge Strategies”部分中所述,您可以用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 dirWithCopyMergeb.txt
    b
    myLineForB
    

    上一次提交确实表示完全合并:

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

    (以Merge开头的行确实证明了这一点)


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

  • 检查<dir>/.gitattributes (与所讨论的路径位于同一目录中):将占据目录中的其他.gitattributes
  • 然后它检查.gitattributes (它位于父目录中),只会设置指令(如果尚未设置的话)
  • 最后它检查$GIT_DIR/info/attributes 。 该文件用于覆盖树中的设置。 它会覆盖<dir>/.gitattributes指令。
  • 通过“组合”,我的意思是“聚合”多重合并驱动程序。
    Nick Green在评论中尝试实际合并合并驱动程序:请参阅“通过python git驱动程序合并pom”。
    但是,正如他的另一个问题所述,只有在冲突的情况下才能起作用(两个分支同时修改)。


    我们有多个不想覆盖的配置文件。 但是.gitignore和.gitattributes在我们的情况下不起作用。 我们的解决方案是将配置文件存储在configs分支中。 然后,允许在git合并期间更改文件,但在合并之后立即使用“git checkout分支 - ”。 每次合并后从configs分支复制我们的配置文件。 详细的计算器答案在这里

    链接地址: http://www.djcxy.com/p/41707.html

    上一篇: How do I tell git to always select my local version for conflicted merges on a specific file?

    下一篇: Push local Git repo to new remote including all branches and tags