git - “git show ..origin/master:somefile”和“git show origin/master:somefile”有什么区别
问题描述
对于上下文,在我自己的功能分支中,我使用以下命令:
> git fetch
> git show ..origin/master:somefile > ../external_folder/somefile
以确保我拥有来自 origin/master 的文件的最新副本以供读取,而不会覆盖我自己的分支。
上面的方法有效,但如果我从 git show 命令中省略了两个点,我得到的文件与我的分支相同,即使一个较新的文件已被推送到 origin/master。
有人能解释一下有什么区别吗?此外,如果它有任何区别,则有问题的文件是一个 blob。
编辑:我错了:
> git show ..origin/master:somefile > ../external_folder/somefile
产生一个空文件,我误解了差异
解决方案
你应该在git show origin/master:somefile
这里使用,没有两个前导点。该git show
命令可能应该抱怨..origin/master:somefile
:向stderr打印一条错误消息,而stdout根本没有输出。
使用我方便的 Git 版本,git show ..<rev>:path
根本不产生任何输出(并且成功退出!),即使给定的路径存在于两个提交中。因此,如果我要使用您的:
git show ..origin/master:somefile > ../external_folder/somefile
我总是会得到一个空 ../external_folder/somefile
文件。我的结论是你的 Git 版本必须早于 Git 1.7.11.3。
长的
<rev1>..<rev2>
语法主要是1表示选择一个范围的提交,范围由调用确定git rev-list
,或多或少就像你运行过一样:
git log ^$(git rev-parse rev1) $(git rev-parse rev2)
如果你git rev-parse
自己运行,你可以更直接地看到这个效果:
$ git rev-parse master~2..master
b994622632154fc3b17fb40a38819ad954a5fb88
^41eae3eaa81c5f2b61b2610ed74de15c4291b318
master
在这个特定的 Git 存储库中,名称选择了 commit b994622632154fc3b17fb40a38819ad954a5fb88
。相对表达式master~2
选择 commit 41eae3eaa81c5f2b61b2610ed74de15c4291b318
。
省略这两个名字中的一个意味着假装我HEAD
是这样写的,因为HEAD
目前是master
,我们也得到:
git rev-parse master~2..
b994622632154fc3b17fb40a38819ad954a5fb88
^41eae3eaa81c5f2b61b2610ed74de15c4291b318
像这样的命令git log
或者git cherry-pick
可以接受这样的一系列提交。此范围表达式选择的提交集是:
- 从非否定(无
^
前缀)提交可到达的所有提交,不包括 - 从否定(
^
-prefixed)提交中可访问的所有提交。
所以如果我们有:
...--E--F--G--H <-- master (HEAD)
then master~2..master
, or - 更短但含义相同 - <code>HEAD~2.. 选择提交G
和H
,因为master
(or HEAD
) 表示提交H
,而master~2
(or HEAD~2
) 表示提交F
。我们选择所有提交,包括 commit H
,然后剔除所有提交,包括 commit F
,只留下G
这里H
。
然而,该git show
命令通常只显示一件事:例如,一个提交或一个文件。所以给它一个范围表达式的概念是没有意义的(但见下文)。但是,该命令可以显示单个文件,并且当您提供的修订表达式命名一个 blob 对象时,它会这样做:
$ git rev-parse master:Makefile
3d3a39fc192d5544a411d4cedb3785473b6f1148
$ git cat-file -t 3d3a39fc192d5544a411d4cedb3785473b6f1148
blob
因此,当git show master:Makefile
给出解析为像这样的单个 blob 对象的修订表达式时,会git show
显示该 blob 对象的内容。
现在考虑:
$ git rev-parse master~2..master:Makefile
3d3a39fc192d5544a411d4cedb3785473b6f1148
^41eae3eaa81c5f2b61b2610ed74de15c4291b318
虽然哈希 ID 很大、很丑、很难记住或正确,但我们实际上可以在这里看到我们给出git show
的是:
- 我们希望看到的 blob 对象的非否定哈希 ID,加上
- 提交 的否定哈希 ID
master~2
。
事实证明,在 Git 1.7.11.3 中首次公开的 commit 修改了命令c5941f1aac071addc1c9b0781c323b588c542420
,使其行为与给定提交范围时git show
非常相似:git log
git show master~2..master
工作起来很像跑步:
git rev-list master~2..master | while read commit; do git show $commit; done
有一些区别。特别是,git log
默认情况下不会显示合并提交的补丁,但git show
默认情况下会显示一个补丁,就像您使用过git log --cc
. (另一个区别在这里不太重要:带有while read commit; do ...; done
序列的 shell 变体必须产生多个git show
命令。)
请注意,以git rev-list
这种方式调用不会产生任何输出:
$ git rev-list master~2..master:Makefile
$
这是因为第二个(非否定的)哈希 ID 是一个 blob 对象的 ID,并且 blob 对象不参与修订遍历。因此,这相当于选择不提交,同时排除所有可从master~2
.
事实上,所有这些都安静地运行和退出,没有抱怨,几乎可以肯定是一个错误。..
我认为,在or表达式中混合提交哈希和标记或 blob 哈希...
应该只会从修订解析代码中得出一个错误。
1副词出现在这里的原因主要是少数命令有特殊处理。特别是,两者都使用两点git diff
和git rebase
/或三点语法玩特殊技巧:它们不只是让git rev-list
工作。
推荐阅读
- powershell - 如何将 PowerShell 脚本(非函数)中的 set-strictMode -version 2 与 param 语句结合使用?
- kubernetes - kubernetes 值文件复制值或创建引用/符号
- r - Hackerrank 测试题:从 IRIS 数据集中找到最大列值的总和
- reactjs - 调用 setInterval 时反应应用程序冻结
- java - 具有多线程支持的应用程序启动和停止功能
- python - 如何使用 BeautifulSoup 将多个 HTML 标签写入具有不同属性的列表?
- java - 其他映射中使用的 Mapstructs 抽象装饰器导致模棱两可的异常
- java - 使用 Android Intent 打开电子邮件
- javascript - 更改模态引导中的文本
- visual-studio - 如何从失败的 VS2019 安装中释放空间