git checkout--合并/--我们的/--他们的似乎在做同样的事情(错误?)?

git checkout--合并/--我们的/--他们的似乎在做同样的事情(错误?)?,git,Git,我正在尝试从另一个分支合并(如果有必要的话,这是一个孤立的分支)。但是,当我执行以下操作时: git merge <branch-name> git合并 它似乎合并正确。但是,如果我做了以下操作: git checkout --merge <branch-name> -- <file-names> git签出--合并-- 当前分支上的大多数更改(如果不是全部的话)都会被删除。无论我使用--merge、--ours还是--theres,结果都是一样的 我

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

git merge <branch-name>
git合并
它似乎合并正确。但是,如果我做了以下操作:

git checkout --merge <branch-name> -- <file-names>
git签出--合并--
当前分支上的大多数更改(如果不是全部的话)都会被删除。无论我使用
--merge
--ours
还是
--theres
,结果都是一样的

我本以为在使用
--merge
标志时,
签出
将执行与
合并
相同的操作,除了指定的文件

发生什么事了?有什么我不明白的吗?

TL;博士 看,这确实允许你做你想做的事

长的
-m
-merge
标志到
git checkout
有多种不同的含义

当与以下部件一起使用时:

git checkout -m <commit-specifier>
git checkout -m [--] <paths>
git签出-m
它或多或少有你想要的含义;问题是它适用于所有路径

当与以下部件一起使用时:

git checkout -m <commit-specifier>
git checkout -m [--] <paths>
git签出-m[--]
它有不同的含义:它意味着Git应该为
中的每个命名路径在具有(或具有)多个更高阶段索引项的文件的工作树副本中重新创建合并冲突


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

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

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

有当前分支和当前提交的概念,但分支只是一个名称(存储在
HEAD
),而提交是一个提交对象,由其散列ID(存储在分支名称中)、永久(大部分)和不可变(完全)标识。提交包含——间接地——每个源文件的完整快照。索引在Git中也是至关重要的,它也存储快照,但与提交不同,索引中的内容是可变的

同时,每个提交存储一组父提交的散列ID,通常正好是一个这样的提交。当您让Git向您显示一些提交时,Git实际上会从父级和提交本身提取所有文件,2然后比较(其中的所有文件)两次提交,并向您显示不同之处。因此,当您查看提交时,它似乎有更改

Git对索引执行相同的操作:它将当前提交与索引进行比较,向您显示差异并调用为提交而进行的更改。然后,如果您现在运行
git commit
,它会将索引(本质上就是您建议的下一次提交的快照)与工作树进行比较。无论索引树和工作树之间有什么不同,Git都会显示这些差异,并调用那些未进行提交的更改。但在所有三组文件中,提交的文件、索引中的文件和工作树中的文件实际上并没有变化,而是快照

一般来说,
git checkout
有很多异常,因为
git checkout
实际上是多个不同的命令,所有这些命令都塞进了一个面向用户的动词中,用于从提交快照提取文件,将这些文件写入索引(以便索引和提交匹配)然后将索引副本写入工作树(以便索引和工作树匹配)。但在执行任何操作之前,它首先检查确保您不会丢失任何未保存的工作,方法是比较当前提交到索引和索引到工作树:如果这两个不匹配,那么git checkout会出错

但是,只要使用
git checkout--
模式,实际上您就切换到了一个完全不同的后端操作。此操作不是从提交开始,而是从索引开始。在过去的某个时候,这些文件是从提交复制到索引的,因此索引中有一些文件集。该集合可能在上次正常签出或硬重置或其他任何操作后已更新:every
git add
意味着将一个文件从工作树复制到索引中,如果工作树文件与索引副本不匹配,那么,现在索引中的文件集合已更改。索引甚至可能有非零阶段项,它们表示不完整的
git merge
正在发生的合并冲突。在这种情况下,索引本质上存储的不是一个而是一些文件的三个冻干副本,从三个输入到早期的
git merge
操作。3但是,无论如何,这种
git checkout
根本不会返回到提交:它只是从索引中获取文件并写入它们,或者对于
-m
重新合并它们,并删除工作树中的任何内容。它这样做时,没有先问是否可以

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

无论如何,底线是,
git checkout-m--path
不起作用