git - 有什么方法可以直接检出 git 的“修改过的”或“未合并的路径”文件?
问题描述
我知道通过以下命令检查两个修改后的文件还有很长的路要走。
git add <filename>
git reset HEAD <filename>
git checkout <filename>
但是是否有一个命令可以检查所有“未合并路径”?
解决方案
您列出的命令序列不会生成--theirs
版本。相反,它会在工作树和索引中生成--ours
版本。有几种方法可以用更少的命令和多个路径名来实现这一点。
第二种短路方法可能是您应该使用的方法:
git checkout --ours path1 path2 ... pathN
或者:
git checkout --theirs path1 path2 ... pathN
其次git add
是那些相同的路径。 非常确定可以丢弃他们或您对合并基础的更改! 特别注意哪个提交是合并基础,这样您就知道要保留什么以及丢弃什么。
要缩短这一步,您可以使用git checkout HEAD
orgit checkout MERGE_HEAD
并跳过该git add
步骤;但见下文。
这里要理解的关键是,每当 Git 检测到冲突时,Git都会将文件的所有三个版本存储在索引中。在这种情况下,您可以访问这三个版本中的任何一个或全部。例如,这是如何git mergetool
获取它称为 BASE、LOCAL 和 REMOTE 的版本,Git 更普遍地将其称为合并 base、HEAD
or--ours
版本,以及另一个 or--theirs
版本。
请记住,索引是 Git 保存每个文件副本的地方,这些文件将进入您的下一次提交。(Git 将其称为index,或staging area,有时也称为cache,具体取决于 Git 文档的哪个部分进行调用。)在正常操作中,任何此类文件都只有一个副本。也就是说,如果您有一个名为的文件,该文件README.txt
在您签出的提交中并且在您可以处理的工作树中,那么您README.txt
在索引中也有一个相同的副本。
工作树中的副本是一个普通文件,格式与您计算机上的任何普通文件相同。存储在HEAD
提交中的提交副本是一种特殊的 Git-only 格式,它不仅被压缩而且完全只读:提交的副本永远不会被更改。当然,您可以进行具有不同版本的新的不同提交README.txt
,但您这样做的方式是首先将新的和不同的提交复制README.txt
到索引中。
请注意,您可以随时查看HEAD
提交中的副本,使用git show HEAD:README.txt
. 同样,您可以使用 来查看索引中的副本git show :README.txt
,其中前导冒号是索引中文件的特殊 Git 语法。
通常,您通过 将新版本复制到索引中git add README.txt
,它只是将当前工作树中的任何内容复制到索引/暂存区域中,覆盖(单个)先前的副本。git merge
但是,当您在orgit cherry-pick
或git revert
or或执行to 合并git stash apply
操作的任何其他操作期间遇到合并冲突时(我喜欢将其称为merge 作为动词),索引将承担新的角色。
虽然索引通常只保存一份. 请记住,合并通过将您的文件版本(您的)与同一文件的某些合并基础版本进行比较,然后将它们的版本与同一合并基础版本进行比较来工作。通过进行这两个单独的比较,Git 可以找出你改变了什么,以及它们改变了什么。然后 Git 组合这两组更改,将这两组更改应用于文件的合并基本版本。也可以看看README.txt
README.txt
README.txt
README.txt
VonC 的答案在这里。
如果 Git 不能自己组合这两组更改,那么 Git 在这一点上所做的就是使用它在索引中所谓的阶段槽。README.txt
Git 可以存储多达四个版本,而不仅仅是索引中的一个。但是,它最多使用三个,并对它们进行编号:
- 暂存槽零保存不冲突的
:README.txt
. - 暂存槽 #1 包含合并基础
1:README.txt
。 - 暂存槽 #2 包含我们的版本
2:README.txt
。 - 暂存槽 #3 保存他们的版本 `:3:README.txt。
当git status
,有或没有--short
,显示未合并的文件时,这意味着在暂存槽 1、2 和 3 中有条目。在这种情况下,不使用槽零!
Git 将冲突的副本写入README.txt
工作树,以便您可以查看冲突并自行解决,但它还将所有三个输入存储在索引中。您可以检查其中任何一个,但插槽 2 和 3 的语法使其变得简单:
git checkout --ours README.txt
从插槽 2 中提取,而:
git checkout --theirs README.txt
从插槽 3 中提取。所有三个版本都保留在索引中,但现在工作树保存我们的(HEAD
版本)或他们的(MERGE_HEAD
版本)。
Running会立即git add
获取工作树中的任何内容,即使它仍然存在合并冲突,并将其写入插槽 0,从而清除插槽 1 到 3。 这使 Git 相信冲突已解决。
您当然可以一次签出或添加多个文件名,因此您可以使用:
git status --porcelain | grep '^UU ' | cut -f2-
生成所有未合并文件的列表(它们的简短状态是UU
),并使用它来制作要提取的文件列表。这种方法不是很健壮(在名称中包含有趣字符或空格的文件存在时失败)但对于简单的情况就足够了:
files=$(git status --porcelain | grep '^UU ' | cut -f2-)
git checkout --theirs $files
git add $files
删除一个步骤
为了缩短这一步,我们可以利用一个关于git checkout
. 使用或让 Git 从索引中提取文件(以其仅 Git 格式)到工作树(以正常格式),这不会更改索引本身的任何内容。但是使用Git 从提交中提取文件,而不是从索引中提取文件。当 Git 这样做时,它首先将该文件复制到索引中。只有在文件在索引中之后才会将文件复制到工作树。git checkout --ours path
git checkout --theirs path
git checkout tree-ish path
git checkout
将文件复制到索引中具有删除文件的任何阶段 1、2 和 3 槽副本的副作用,将文件写入暂存槽零。因此,如果该文件以前未合并,则它突然变为合并。
请注意,如果我们处于冲突合并中,我们正在合并的提交的哈希 ID 存储在MERGE_HEAD
. 如果我们正在挑选樱桃,那么我们挑选的提交的哈希 ID 在CHERRY_PICK_HEAD
. (有关它们存储哈希 ID 的位置,请参阅其他命令。)
因此,即使暂存槽 2 中HEAD
的副本来自提交,而暂存槽 3 中的副本MERGE_HEAD
来自到暂存槽零。效果是解决合并问题,同时还选择我们的 ( ) 或他们的 ( ) 版本的文件。HEAD
MERGE_HEAD
HEAD
MERGE_HEAD
因此,对于没有难命名的文件,命令:
git checkout HEAD $(git status --porcelain | grep '^UU ' | cut -f2-)
做选择的诀窍--ours
,而:
git checkout MERGE_HEAD $(git status --porcelain | grep '^UU ' | cut -f2-)
做选择的诀窍--theirs
(git merge
仅限!)。 同样,除非您确切知道自己在做什么,否则不要使用它。
推荐阅读
- android - 设计带有弯曲边缘的 ImageView Android
- javascript - 如何在 Webrtc 中保存客户端的流帧?
- sql - 按设备 ID 分组保存 latest100 条记录
- facebook - 使用 Unity Facebook SDK 在 Facebook 中发出应用程序到用户请求
- tabs - 无法重命名 LWC 中的 navigationmixing.navigate url 选项卡
- python-3.x - vaex:如何限制核心/线程/进程的数量?
- python - 如何在没有应用的情况下获取熊猫 DataFrame 的先前非 NaN 值来计算?
- excel - 单词表提取到excel
- flutter - Flutter:如何在对列表元素进行排序时显示动画?
- javascript - React Native SectionList 拆分日期