交互式合并使用git和未跟踪的本地文件跟踪的文件

时间:2015-05-23 13:24:40

标签: git command-line merge diff interactive

我使用了一些软件包(比如gitlab),你可以通过他们的git repo克隆来安装。它们通常带有一些legend('indiscernible relation','cernible relation' ,'equivalence relation') (在版本控制下),您可以将其复制到您自己的config.example文件中(不受版本控制,甚至可以在config中忽略)并根据您的需要进行调整。 / p>

更新上游软件包时,例如更改配置文件选项,这些选项显然只会反映在.gitignore中。

我是否缺少一系列git命令可以帮助我将config.example的更改与config.example中的新更改进行比较,甚至可以将它们交互式地合并到我的本地{{1}文件?

如果我能在upstream/HEAD中获得类似交互式补丁模式的话,那会很棒。

7 个答案:

答案 0 :(得分:2)

  • 您可以将vim用作vimdiff的合并工具。
  • Emacs也可以使用ediff-mode
  • 执行此操作

答案 1 :(得分:2)

你可能会以多种方式解决这个问题。我能想到两个:git-merge-file和好老patchgit-merge-file方法提供了一些交互性,而patch方法则不提供任何交互性。

git-merge-file

的解决方案

假设您有一个原始文件config.example,您可以使用该文件创建本地无版本文件config.local。现在,当上游更新config.example时,您可以按照以下步骤合并任何新更改。

$ git fetch
$ git show master:config.example > config.example.base
$ git show origin/master:config.example > config.example.latest
$ git merge-file config.local config.example.base config.example.latest

这将使用通常的冲突标记更新config.local,然后您必须使用自己喜欢的合并工具解决(Emacs中的ediff很好,我确定Vim有类似的模式)。例如,以下三个文件

<强> config.example.base

Original: 
          some config

<强> config.example.latest

Original: 
          some config

Upstream:
          new upstream config

<强> config.local

Original: 
          some config

My changes:
          some other config

将合并为:

Original: 
          some config

<<<<<<< config.local
My changes:
          some other config
=======
Upstream:
          new upstream config
>>>>>>> config.example.latest

你可以不费力地编写脚本。顺便说一下,git-merge-file可以对任何3个文件进行操作,它们不需要在git下进行版本控制。这意味着可以使用它来合并任何三个文件!

patch的解决方案:

假设文件名相同,config.localconfig.example,以下内容应该有效。

$ git fetch
$ git diff master..origin/master -- config.example | sed -e 's%\(^[-+]\{3\}\) .\+%\1 config.local%g' > /tmp/mypatch
$ patch < /tmp/mypatch

答案 2 :(得分:2)

git checkout --patch选择差异,这里最简单的可能是将你的内容放在上游路径上,做到这一点,然后清理:

cp config  config.example
git checkout -p upstream   config.example
mv config.example  config
git checkout @  config.example

它将为您提供git add --patch的双差异大块选择。

答案 3 :(得分:1)

如果你想要完整的git合并,你可以通过设置一个索引条目git read-tree来获取任意内容的git,然后在该条目上调用git的普通合并驱动程序。 Git将不同的内容版本称为“阶段”;他们是1:原来的,2:你的,3:他们的。合并比较从1到2和从1到3的变化,并做它的事情。要进行设置,请使用git update-index

orig_example=        # fill in the commit with the config.example you based yours on
new_upstream=        # fill in the name of the upstream branch

( while read; do printf "%s %s %s\t%s\n" $REPLY; done \
| git update-index --index-info ) <<EOD
100644 $(git rev-parse $orig_example:config.example)  1 config
100644 $(git hash-object -w config)                   2 config
100644 $(git rev-parse $new_upstream:config.example)  3 config
EOD

并且您已为该路径合并了自定义内容。现在去做:

git merge-index git-merge-one-file -- config

它会自动缓存或保留通常的冲突粪便,根据需要进行修复,并根据需要git rm --cached --ignore-unmatch(或保留)索引条目。

顺便说一下,您放入索引的路径名(此处所有三个条目中的“config”)不一定存在或与任何事情有关。你可以将它命名为“wip”或“deleteme”或任何你想要的东西。合并是索引条目中id'd的内容。

我认为这可能会在这里做你想做的事。如果您确实想要从上游更改中进行选择,您可以将自己的内容放在config.example并执行git checkout -p upstream -- config.example,这与git add -p相反,然后按照它们的方式回放

答案 4 :(得分:0)

要使用config.example中的相应文件在本地仓库中区分upstream/HEAD,您可以运行:

git diff upstream/HEAD config.example

不幸的是我不知道如何让git直接将更改应用于git不跟踪的文件。

答案 5 :(得分:0)

a tool called sdiff可能会做你想要的。

使用sdiff -o config config.example config

调用它(在您的情况下)

答案 6 :(得分:0)

以下内容应该有效:

git diff <some-args> | perl -pe 's/path\/to\/changes\/file/path\/other/g' > t
patch -p1 < t 
rm t