通过设置非零阶段条目值手动将具有合并冲突的文件添加到 git 索引
Manually adding a file with a merge-conflict to the git index by setting non-zero stage entry values
我在 git 存储库中提交了两个文件,一个 original
文件和一个 derived
文件。
derived
基于 original
但有一些修改(即 diff original derived
产生一些小输出)。
每当我修改 original
文件时,我也想通过脚本半自动地将相同的更改应用到 derived
。有一个有用的 git 命令,叫做 git merge-file
可以让我做到这一点。
我的情况是我想将索引中 original
的更改(即 original
已修改但尚未提交)应用到 derived
文件,所以我做了一些事情像这样:
git cat-file -p HEAD:original >orignal.base
git merge-file derived original.base original
rm -f original.base
现在 derived
应该具有应用于 original
的相同更改(并且 diff original derived
应该或多或少没有变化)。
但是,有可能发生合并冲突,在这种情况下git-merge-file returns一个非零值,并留下输出文件(derived
) 与合并冲突标记(<<<<<<<
、=======
和 >>>>>>>
)。这就是我的问题所在。
我想要做的是,在合并冲突的情况下,而不是让 derived
在索引中被标记为 'modified',我希望它显示为 'both modified'就像发生合并冲突时(不太像 git merge
,更像 git stash apply
)。
我查看了所有可用的 git 命令,有一些像 git read-tree -m
几乎可以满足我的要求,但用于树而不是 blob。
所以我的想法是使用类似 git update-index
的东西。阅读一下 git 索引的工作原理,like in this question,索引中的文件有一个所谓的 'stage entries',通常为 0,例如对于上述文件,我们会有
$ git ls-files --stage
100644 cd2732a3aeeb97c20b5dc809cc6350fd7fbfb944 0 derived
100644 4b48deed3a433909bfd6b6ab3d4b91348b6af464 0 original
但是在合并冲突之后(例如在失败之后 git stash apply
它看起来像这样:
$ git ls-files --stage
100644 cd2732a3aeeb97c20b5dc809cc6350fd7fbfb944 1 derived
100644 68bc18a75908806fd6c9c816b7370f4797a6be15 2 derived
100644 d4cda09e1616383549548d7212cdcb86b4dda596 3 derived
100644 4b48deed3a433909bfd6b6ab3d4b91348b6af464 0 original
其中 1
是基础文件,2
是本地修改的文件,3
是隐藏文件。工作目录中的文件包含 git merge-file
也产生的合并冲突标记。但是git update-index
不支持设置这些'stage values'
所以我想做的是以下内容,以防 git merge-file
失败:
- 将文件
original.base
添加为 1 derived
(基础)
- 文件
original
为2 derived
('our'修改)
- 并将原
derived
文件作为3 derived
('their'修改)放入索引
- (在工作树中保留带有合并冲突标记的
derived
文件)
想要这样做的原因是:
- 用户很明显存在需要解决的合并冲突
git commit
将失败,直到冲突得到解决
- 用户可以使用
git mergetool
来解决GUI应用程序中的冲突,这在git merge-file
的正常结果中是不可能的
有没有办法实现我想做的事情
- 通过将文件添加到具有非零 'stage entry' 的索引,如上所述
- 或者用我想不到的另一种simpler/better方式来达到相同的结果
谢谢。
作为bk2204 said in a comment,这是错误的处理方式。但是让我们回答标题问题。如果您 想要创建一个冲突的索引条目,git update-index
确实是正确的(也是唯一的)工具:
- 根据定义,当且仅当索引条目具有非零阶段编号时,它才是冲突/未合并的。
- 只有
git update-index
能够插入具有非零阶段编号的索引条目。
But git update-index
does not support setting these 'stage values' ...
这种说法是错误的。但是,设置一个非零的分段编号并不容易。仔细阅读 the git update-index
documentation,我们发现只有一种方法可以做到这一点:
--index-info
Read index information from stdin.
USING --INDEX-INFO
--index-info
is a more powerful mechanism that lets you feed multiple entry definitions from the standard input, and designed specifically for scripts. It can take inputs of three formats:
mode SP type SP sha1 TAB path
This format is to stuff git ls-tree
output into the index.
mode SP sha1 SP stage TAB path
This format is to put higher order stages into the index file and matches git ls-files --stage
output.
[format 3 snipped; boldface above is mine]
To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the third format.
进一步注意,因为您必须将 哈希 ID 放入索引中,所以您必须首先确保您想要的数据以 blob object 的形式存在。为此,请使用 git hash-object -w -t blob
(尽管您可以省略 -t blob
,因为这是默认值)。
So what I want to do is the following, in case git merge-file
fails:
- Add the file original.base as 1 derived (base)
因为 original.base
已经有一个哈希 ID(例如,4b48deed3a433909bfd6b6ab3d4b91348b6af464
),您可以直接使用它。假设此时在 $hash1
中。
- the file original as 2 derived ('our' modification)
这也有一个现有的哈希 ID,比方说 $hash2
。
- and the original derived file as 3 derived ('their' modification) into the index
为此,您必须再次导出文件(我想我可能有 mis-read 问题中的内容)和 运行 git hash-object
:
hash3=$(git hash-object -w < original-derived-data)
您现在可以删除文件(此处 original-derived-data
)。
- (keep the derived file with the merge-conflict markers in the worktree)
为此,不需要任何内容。现在您有了三个哈希 ID:
TAB=$'\t' # make sure your shell supports this syntax
git update-index --index-info <<end
0 blob $hash1 0${TAB}derived
100644 blob $hash1 1${TAB}derived
100644 blob $hash2 2${TAB}derived
100644 blob $hash3 3${TAB}derived
end
“here-doc”(<<end
) 将扩展 $
个变量,因为我们没有引用 end-word。 0 blob $hash1 0${TAB}derived
行中的散列是无关紧要的:mode 0
是我们真正想要的,如果有条目则删除该条目。其余三行使用现有数据的现有哈希 ID($hash1
和 $hash2
)和新 computed-and-saved 数据的新哈希 ID($hash3
).
请注意,默认情况下,从您使用 git hash-object -w
计算索引开始,您只有 14 天的时间将 $hash3
插入索引。如果您的脚本需要比 运行 更长的时间,git gc
可能 运行 并删除您编写的 object。当然,如果您的脚本需要 14 天才能达到 运行,那么其他地方可能就大错特错了。 :-)
我在 git 存储库中提交了两个文件,一个 original
文件和一个 derived
文件。
derived
基于 original
但有一些修改(即 diff original derived
产生一些小输出)。
每当我修改 original
文件时,我也想通过脚本半自动地将相同的更改应用到 derived
。有一个有用的 git 命令,叫做 git merge-file
可以让我做到这一点。
我的情况是我想将索引中 original
的更改(即 original
已修改但尚未提交)应用到 derived
文件,所以我做了一些事情像这样:
git cat-file -p HEAD:original >orignal.base
git merge-file derived original.base original
rm -f original.base
现在 derived
应该具有应用于 original
的相同更改(并且 diff original derived
应该或多或少没有变化)。
但是,有可能发生合并冲突,在这种情况下git-merge-file returns一个非零值,并留下输出文件(derived
) 与合并冲突标记(<<<<<<<
、=======
和 >>>>>>>
)。这就是我的问题所在。
我想要做的是,在合并冲突的情况下,而不是让 derived
在索引中被标记为 'modified',我希望它显示为 'both modified'就像发生合并冲突时(不太像 git merge
,更像 git stash apply
)。
我查看了所有可用的 git 命令,有一些像 git read-tree -m
几乎可以满足我的要求,但用于树而不是 blob。
所以我的想法是使用类似 git update-index
的东西。阅读一下 git 索引的工作原理,like in this question,索引中的文件有一个所谓的 'stage entries',通常为 0,例如对于上述文件,我们会有
$ git ls-files --stage
100644 cd2732a3aeeb97c20b5dc809cc6350fd7fbfb944 0 derived
100644 4b48deed3a433909bfd6b6ab3d4b91348b6af464 0 original
但是在合并冲突之后(例如在失败之后 git stash apply
它看起来像这样:
$ git ls-files --stage
100644 cd2732a3aeeb97c20b5dc809cc6350fd7fbfb944 1 derived
100644 68bc18a75908806fd6c9c816b7370f4797a6be15 2 derived
100644 d4cda09e1616383549548d7212cdcb86b4dda596 3 derived
100644 4b48deed3a433909bfd6b6ab3d4b91348b6af464 0 original
其中 1
是基础文件,2
是本地修改的文件,3
是隐藏文件。工作目录中的文件包含 git merge-file
也产生的合并冲突标记。但是git update-index
不支持设置这些'stage values'
所以我想做的是以下内容,以防 git merge-file
失败:
- 将文件
original.base
添加为1 derived
(基础) - 文件
original
为2 derived
('our'修改) - 并将原
derived
文件作为3 derived
('their'修改)放入索引 - (在工作树中保留带有合并冲突标记的
derived
文件)
想要这样做的原因是:
- 用户很明显存在需要解决的合并冲突
git commit
将失败,直到冲突得到解决- 用户可以使用
git mergetool
来解决GUI应用程序中的冲突,这在git merge-file
的正常结果中是不可能的
有没有办法实现我想做的事情
- 通过将文件添加到具有非零 'stage entry' 的索引,如上所述
- 或者用我想不到的另一种simpler/better方式来达到相同的结果
谢谢。
作为bk2204 said in a comment,这是错误的处理方式。但是让我们回答标题问题。如果您 想要创建一个冲突的索引条目,git update-index
确实是正确的(也是唯一的)工具:
- 根据定义,当且仅当索引条目具有非零阶段编号时,它才是冲突/未合并的。
- 只有
git update-index
能够插入具有非零阶段编号的索引条目。
But
git update-index
does not support setting these 'stage values' ...
这种说法是错误的。但是,设置一个非零的分段编号并不容易。仔细阅读 the git update-index
documentation,我们发现只有一种方法可以做到这一点:
--index-info
Read index information from stdin.USING --INDEX-INFO
--index-info
is a more powerful mechanism that lets you feed multiple entry definitions from the standard input, and designed specifically for scripts. It can take inputs of three formats:
mode SP type SP sha1 TAB path
This format is to stuff
git ls-tree
output into the index.mode SP sha1 SP stage TAB path
This format is to put higher order stages into the index file and matches
git ls-files --stage
output.[format 3 snipped; boldface above is mine]
To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the third format.
进一步注意,因为您必须将 哈希 ID 放入索引中,所以您必须首先确保您想要的数据以 blob object 的形式存在。为此,请使用 git hash-object -w -t blob
(尽管您可以省略 -t blob
,因为这是默认值)。
So what I want to do is the following, in case
git merge-file
fails:
- Add the file original.base as 1 derived (base)
因为 original.base
已经有一个哈希 ID(例如,4b48deed3a433909bfd6b6ab3d4b91348b6af464
),您可以直接使用它。假设此时在 $hash1
中。
- the file original as 2 derived ('our' modification)
这也有一个现有的哈希 ID,比方说 $hash2
。
- and the original derived file as 3 derived ('their' modification) into the index
为此,您必须再次导出文件(我想我可能有 mis-read 问题中的内容)和 运行 git hash-object
:
hash3=$(git hash-object -w < original-derived-data)
您现在可以删除文件(此处 original-derived-data
)。
- (keep the derived file with the merge-conflict markers in the worktree)
为此,不需要任何内容。现在您有了三个哈希 ID:
TAB=$'\t' # make sure your shell supports this syntax
git update-index --index-info <<end
0 blob $hash1 0${TAB}derived
100644 blob $hash1 1${TAB}derived
100644 blob $hash2 2${TAB}derived
100644 blob $hash3 3${TAB}derived
end
“here-doc”(<<end
) 将扩展 $
个变量,因为我们没有引用 end-word。 0 blob $hash1 0${TAB}derived
行中的散列是无关紧要的:mode 0
是我们真正想要的,如果有条目则删除该条目。其余三行使用现有数据的现有哈希 ID($hash1
和 $hash2
)和新 computed-and-saved 数据的新哈希 ID($hash3
).
请注意,默认情况下,从您使用 git hash-object -w
计算索引开始,您只有 14 天的时间将 $hash3
插入索引。如果您的脚本需要比 运行 更长的时间,git gc
可能 运行 并删除您编写的 object。当然,如果您的脚本需要 14 天才能达到 运行,那么其他地方可能就大错特错了。 :-)