当上游软件包更新并更改配置文件选项时,这只会反映在 config.example 中。
是否有一系列 git 命令可以帮助我比较 config.example 文件的更改与 upstream/HEAD 中的新文件,并可能以交互方式将它们合并到我的本地 config 文件中?
如果我能得到类似于 git add/commit --interactive 的交互式补丁模式那就太好了。
当上游软件包更新并更改配置文件选项时,这只会反映在 config.example 中。
是否有一系列 git 命令可以帮助我比较 config.example 文件的更改与 upstream/HEAD 中的新文件,并可能以交互方式将它们合并到我的本地 config 文件中?
如果我能得到类似于 git add/commit --interactive 的交互式补丁模式那就太好了。
vimdiff
将vim
作为合并工具。Emacs
也可以使用ediff-mode
进行此操作。git checkout --patch
选择差异块,最简单的方法是将您的内容放在上游路径中,然后进行清理:
cp config config.example
git checkout -p upstream config.example
mv config.example config
git checkout @ config.example
git add --patch
中获取你所需的两个差异块选择。git-merge-file
或是传统的patch
。使用git-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.local
和 config.example
,以下方法应该可以运行。$ git fetch
$ git diff master..origin/master -- config.example | sed -e 's%\(^[-+]\{3\}\) .\+%\1 config.local%g' > /tmp/mypatch
$ patch < /tmp/mypatch
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”或任何您想要的名称。合并是在索引条目中标识的内容。
我认为这可能符合您的要求。如果您确实想从上游更改中挑选和选择,可以在config.example中放置自己的内容,然后执行git checkout -p upstream -- config.example
,这相当于git add -p
的反向操作,然后将事情恢复到原来的状态。
cp config config.example ; git checkout -p upstream -- config.example
然后交互式地决定如何合并更改,最后运行mv config.example config && git reset config.example && git checkout -- config.example
来设置回原样。如果您将最后一段拆分为一个单独的答案,我会接受它,因为它清晰简明。 - Jörn Hees以下代码应该可以正常工作:
git diff <some-args> | perl -pe 's/path\/to\/changes\/file/path\/other/g' > t
patch -p1 < t
rm t
如果你想要将本地仓库中的config.example
文件与upstream/HEAD
中对应的文件进行比较,可以运行以下命令:
git diff upstream/HEAD config.example
很遗憾,我不知道有什么方法可以让git直接应用对于未被跟踪的文件所做的更改。
git add -p
那样交互式,这意味着我无法真正审查新的配置选项。尽管如此,我还是会点赞的,因为这可能是其他人前进的方式。 - Jörn Hees