交互式合并使用 git 跟踪的文件和未跟踪的本地文件
Interactively merge files tracked with git and untracked local files
我使用了几个软件包(例如 gitlab),您可以通过从他们的 git 存储库中克隆来安装这些软件包。它们通常带有一些 config.example
(在版本控制下),您可以将其复制到自己的 config
文件(不受版本控制,甚至在 .gitignore
中被忽略)并适应您的需要。
更新上游包时,例如更改配置文件选项时,显然只会反映在 config.example
。
是否有我遗漏的 git 命令链可以帮助我将 config.example
的更改与 upstream/HEAD
中的新更改进行比较,甚至可能以交互方式合并它们进入我的本地 config
文件?
如果我能在 git add/commit --interactive
.
中获得类似交互式补丁模式的东西,那就太棒了
要将本地存储库中的 config.example
与 upstream/HEAD
中的相应文件进行比较,您可以 运行:
git diff upstream/HEAD config.example
不幸的是,我不知道有什么方法可以让 git 直接将更改应用到 git 不跟踪的文件。
a tool called sdiff 可能会满足您的要求。
使用 sdiff -o config config.example config
调用它(在您的情况下)
- 您可以将
vim
用作与 vimdiff
的合并工具。
Emacs
也可以用 ediff-mode
来做到这一点。
以下应该有效:
git diff <some-args> | perl -pe 's/path\/to\/changes\/file/path\/other/g' > t
patch -p1 < t
rm t
如果您想要完整的 git 合并,您可以 git 通过像 git read-tree
那样设置索引条目然后调用 [=32] 来处理任意内容=] 的正常合并驱动程序就在那个条目上。 Git指的是不同的内容版本为"stages";它们是 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。
我认为这很可能会满足您的要求。如果你真的想从上游变化中挑选,你可以把你自己的内容放在 config.example 并做 git checkout -p upstream -- config.example
,这与 git add -p
相反,然后把事情放回去他们是。
您可以通过多种方式解决这个问题。我能想到两个:git-merge-file
和好旧的 patch
。 git-merge-file
方法提供了一些交互性,而 patch
方法提供了 none.
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\}\) .\+% config.local%g' > /tmp/mypatch
$ patch < /tmp/mypatch
git checkout --patch
选择 diff hunks,这里最简单的可能是将您的内容放在上游路径,这样做,然后清理:
cp config config.example
git checkout -p upstream config.example
mv config.example config
git checkout @ config.example
这将使您从 git add --patch
.
中选择两个不同的大块头
我使用了几个软件包(例如 gitlab),您可以通过从他们的 git 存储库中克隆来安装这些软件包。它们通常带有一些 config.example
(在版本控制下),您可以将其复制到自己的 config
文件(不受版本控制,甚至在 .gitignore
中被忽略)并适应您的需要。
更新上游包时,例如更改配置文件选项时,显然只会反映在 config.example
。
是否有我遗漏的 git 命令链可以帮助我将 config.example
的更改与 upstream/HEAD
中的新更改进行比较,甚至可能以交互方式合并它们进入我的本地 config
文件?
如果我能在 git add/commit --interactive
.
要将本地存储库中的 config.example
与 upstream/HEAD
中的相应文件进行比较,您可以 运行:
git diff upstream/HEAD config.example
不幸的是,我不知道有什么方法可以让 git 直接将更改应用到 git 不跟踪的文件。
a tool called sdiff 可能会满足您的要求。
使用 sdiff -o config config.example config
- 您可以将
vim
用作与vimdiff
的合并工具。 Emacs
也可以用ediff-mode
来做到这一点。
以下应该有效:
git diff <some-args> | perl -pe 's/path\/to\/changes\/file/path\/other/g' > t
patch -p1 < t
rm t
如果您想要完整的 git 合并,您可以 git 通过像 git read-tree
那样设置索引条目然后调用 [=32] 来处理任意内容=] 的正常合并驱动程序就在那个条目上。 Git指的是不同的内容版本为"stages";它们是 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。
我认为这很可能会满足您的要求。如果你真的想从上游变化中挑选,你可以把你自己的内容放在 config.example 并做 git checkout -p upstream -- config.example
,这与 git add -p
相反,然后把事情放回去他们是。
您可以通过多种方式解决这个问题。我能想到两个:git-merge-file
和好旧的 patch
。 git-merge-file
方法提供了一些交互性,而 patch
方法提供了 none.
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\}\) .\+% config.local%g' > /tmp/mypatch
$ patch < /tmp/mypatch
git checkout --patch
选择 diff hunks,这里最简单的可能是将您的内容放在上游路径,这样做,然后清理:
cp config config.example
git checkout -p upstream config.example
mv config.example config
git checkout @ config.example
这将使您从 git add --patch
.