git checkout --merge/--ours/--theirs 似乎在做同样的(错误的?)事情?

阿德里安

我正在尝试从另一个分支合并(如果重要的话,它是一个孤立的分支)。但是,当我执行以下操作时:

git merge <branch-name>

它似乎正确合并。但是,如果我执行以下操作:

git checkout --merge <branch-name> -- <file-names>

当前分支上的大多数(如果不是全部)更改都会被清除。无论我使用--merge,--ours还是--theirs,结果都是一样的。

我原以为checkout使用--merge标志的时候会做同样的事情merge,除了指定的文件。

这是怎么回事?有什么我不明白的吗?

周二

TL; 博士

git merge-file命令,这确实让你做你想要的。

-m--merge以标志git checkout具有多种不同的含义。

与以下一起使用时:

git checkout -m <commit-specifier>

它或多或少具有您想要的含义;问题是它适用于所有路径。

与以下一起使用时:

git checkout -m [--] <paths>

它有不同的含义:这意味着 Git 应该,对于 中的每个命名路径<paths>,在具有(或具有)多个更高阶段索引条目的文件的工作树副本中重新创建合并冲突。


这里有一个更基本的问题。其中一部分只是棘手的用语——例如,我们都说“工作树中的变化”——但另一部分在于如何思考 Git 的作用:

...当前分支上的大部分更改(如果不是全部)都被清除了

这表明您正在考虑每个文件的工作树副本中的内容作为更改,而实际情况并非如此。Git 不会在任何地方存储更改,1并且文件的工作树副本主要供您根据需要使用:Git 主要使用快照,文件以我喜欢称之为冻结干燥的格式存储在blob 对象中与提交相关联并在索引中。

这里一个概念,当前分支,也当前提交,但分支仅仅是一个名称(存储在HEAD),而提交的是一个commit对象,通过它的哈希ID标识(存储在分支名),永久(大部分)和不可变(完全)。提交包含——间接地——每个源文件的完整快照。索引也是 Git 中的关键,它也存储快照,但与提交不同的是,索引中的内容是可变的。

同时,每个提交都存储了一组提交的哈希ID——通常就是一个这样的提交。当您让 Git 向您展示一些提交时,Git 实际上会从父项提交本身中提取所有文件然后2比较(其中的所有文件)两次提交并显示不同因此,当您查看提交时,它似乎发生了变化。

Git 对索引执行相同的技巧:它比较当前提交与索引,显示差异并调用为 commit 暂存的更改然后,它比较指数基本上是快照,你求婚会下一个承诺,如果你跑了git commit,现在到工作树。无论索引和工作树之间有何不同,Git 都会显示这些差异,称这些更改未暂存为 commit但是在所有三组文件中——提交的文件、索引中的文件和工作树中的文件——实际上没有变化,而是快照

什么git checkout通常做的那样-有一堆的例外,因为git checkout实在是多个不同的命令都塞进一个面向用户的动词是提取文件从提交快照,写这些文件到指数(使指数和提交匹配)然后将索引副本写入工作树(以便索引和工作树匹配)。但在执行任何操作之前,它首先检查以确保您不会丢失任何未保存的工作,方法是将当前提交与索引以及索引与工作树进行比较:如果这两者不匹配,则有有什么东西git checkout会破坏。

git checkout -- <paths>但是,一旦您使用该模式,您实际上就会切换到完全不同的后端操作。此操作不是从提交开始,而是从索引开始。这些文件在过去的某个时间从提交复制索引,因此索引具有一些文件集。该集合可能自上次正常检出或硬重置或其他任何内容以来已更新:everygit add意味着将文件从工作树复制到 index,如果工作树文件与索引副本不匹配,那么现在它这样做索引中的文件集已更改。索引甚至可能有非零阶段条目,表示来自不完整git merge. 在这种情况下,索引本质上存储的不是一个而是三个一些文件的冻干副本,从三个输入到更早的git merge操作。3但是,无论如何,这种类型git checkout根本不会回到提交:它只是从索引中获取文件并写入它们,或者-m重新合并它们,并破坏工作树中的任何内容。它在没有首先询问是否可以的情况下这样做4

(编辑:还有git checkout --patch,但这实际上调用了第三种模式。补丁操作,它比较文件的两个版本,并让您选择此差异的一部分以应用于两个版本之一,实际上是由 Perl 程序处理的运行git diff在两个版本之间。这个工具git checkout --patchgit add --patchgit stash --patch,和git reset --patch)。

无论如何,底线是git checkout -m -- path不做你想做的。可以得到你想要的,但不能使用git checkout. 相反,您需要做的是提取您想要传递给的三个输入文件——git merge将这三个文件放在任何地方;他们甚至不需要在工作树库本身,然后运行git merge-file命令在他们身上。


1好吧,除非您存储 的输出git diff,或者作为特殊情况,保存的合并的每个部分都与 发生冲突git rerere,但所有这些都低于正常的可见性级别。

2由于内部冻干文件格式,Git 实际上不必费心提取相同的文件,只提取那些至少有一点不同的文件。

3从技术上讲,每个文件最多三个条目。例如,在修改/删除冲突等情况下,对于某个文件,您将只有两个条目。此外,当您完成合并冲突和git add文件的解决后,更高阶段的条目将消失。但是,在您提交之前,那些更高阶段的条目会存储在一个秘密的、不可见的“REUC”类型的索引条目中,以便您可以使用它git checkout -m来恢复冲突。无法查看或保存这个不可见条目,这是当前索引格式的几个缺陷之一。

4从人性化设计的角度来说,这个特别不好,因为其他形式的git checkout很小心,不丢工作。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

git merge -s递归-X ours与git merge -s ours吗?

来自分类Dev

如何对多个文件(或所有未合并的文件)执行“ git checkout --theirs”

来自分类Dev

无论如何,Jenkins Git插件是否可以将merge-strategy选项设置为'theirs'?

来自分类Dev

解决`git checkout master --patch`之后的“ git merge master”冲突

来自分类Dev

.gitattributes与merge = ours的正确用法是什么

来自分类Dev

是否有可能仅在冲突文件的冲突区域中执行“我们的”,从而选择性地进行“ git checkout --ours”

来自分类Dev

git checkout发生错误。路径太长

来自分类Dev

Jenkins Groovy管道-git checkout错误

来自分类Dev

使用“ mine”或“ theirs”解决git中多个合并冲突的工具

来自分类Dev

使用“ mine”或“ theirs”解决git中多个合并冲突的工具

来自分类Dev

git checkout --merge <tree-ish>-<paths>不能按预期工作

来自分类Dev

它能够还原`git rebase origin / master --strategy = ours`吗?

来自分类Dev

它能够还原`git rebase origin / master --strategy = ours`吗?

来自分类常见问题

“ git checkout-”。vs git checkout

来自分类Dev

Git Checkout远程分支

来自分类Dev

等价于git的“ svn checkout”?

来自分类Dev

JGIT:git checkout-

来自分类Dev

git checkout混淆了

来自分类Dev

撤消git checkout --orphan

来自分类Dev

Git Checkout澄清

来自分类Dev

git checkout每次提交

来自分类Dev

撤消 git checkout --

来自分类Dev

PowerShell ISE在git checkout上引发错误

来自分类Dev

git checkout master从mybranch切换时返回错误

来自分类Dev

git merge .idea /工作区错误

来自分类Dev

git merge或git rebase?

来自分类Dev

“ git checkout-*”返回“错误:pathspec与git已知的任何文件都不匹配”

来自分类Dev

并发git checkout / add / commit

来自分类常见问题

git checkout ...有什么作用?

Related 相关文章

  1. 1

    git merge -s递归-X ours与git merge -s ours吗?

  2. 2

    如何对多个文件(或所有未合并的文件)执行“ git checkout --theirs”

  3. 3

    无论如何,Jenkins Git插件是否可以将merge-strategy选项设置为'theirs'?

  4. 4

    解决`git checkout master --patch`之后的“ git merge master”冲突

  5. 5

    .gitattributes与merge = ours的正确用法是什么

  6. 6

    是否有可能仅在冲突文件的冲突区域中执行“我们的”,从而选择性地进行“ git checkout --ours”

  7. 7

    git checkout发生错误。路径太长

  8. 8

    Jenkins Groovy管道-git checkout错误

  9. 9

    使用“ mine”或“ theirs”解决git中多个合并冲突的工具

  10. 10

    使用“ mine”或“ theirs”解决git中多个合并冲突的工具

  11. 11

    git checkout --merge <tree-ish>-<paths>不能按预期工作

  12. 12

    它能够还原`git rebase origin / master --strategy = ours`吗?

  13. 13

    它能够还原`git rebase origin / master --strategy = ours`吗?

  14. 14

    “ git checkout-”。vs git checkout

  15. 15

    Git Checkout远程分支

  16. 16

    等价于git的“ svn checkout”?

  17. 17

    JGIT:git checkout-

  18. 18

    git checkout混淆了

  19. 19

    撤消git checkout --orphan

  20. 20

    Git Checkout澄清

  21. 21

    git checkout每次提交

  22. 22

    撤消 git checkout --

  23. 23

    PowerShell ISE在git checkout上引发错误

  24. 24

    git checkout master从mybranch切换时返回错误

  25. 25

    git merge .idea /工作区错误

  26. 26

    git merge或git rebase?

  27. 27

    “ git checkout-*”返回“错误:pathspec与git已知的任何文件都不匹配”

  28. 28

    并发git checkout / add / commit

  29. 29

    git checkout ...有什么作用?

热门标签

归档