git - 如何在 Git stashes 中查看未跟踪的文件
问题描述
我经常将我所做的工作存储在新的(未跟踪的)文件中,我希望以后能够找到这项工作。找到它的明显方法似乎是git show
。
我刚刚发现 Git 在我使用时完全忽略了这些文件git show
(但幸运的是在弹出隐藏代码时没有忽略它们),这使得可靠地找到隐藏代码似乎是不可能的。
为了使这个更具体,假设我有
On branch feature/request-reappointment
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/models/job.rb
modified: config/initializers/environmental_email_interceptor.rb
Untracked files:
(use "git add <file>..." to include in what will be committed)
app/models/receipt.rb
db/migrate/20200130091050_create_receipts.rb
no changes added to commit (use "git add" and/or "git commit -a")
如果我表演
git stash save -u 'miscellaneous improvements'
git show stash@{0}
Git 将忽略未跟踪的文件。这不仅是 Git 从命令行的行为,而且像 Fork 和 GitKraken 这样的 GUI 工具也有同样的问题,大概是继承自 Git。
如何显示存储的实际内容,包括未跟踪的文件?
更新:
尽管 GitKraken 和 Fork 未能在任何存储中显示未跟踪的文件,但 Tower 2(一个旧版本,因为我拒绝切换到他们基于订阅的定价模型)成功了。我必须给他们一些信任,如果不是这个价格,我今天会买一本新的。
解决方案
TL;博士
要查看文件名,请使用git ls-tree -r stash^3
; 要查看它们的内容,请使用git show stash^3
.
长
如何显示存储的实际内容,包括未跟踪的文件?
未跟踪的文件通常不在 stash 中。有一个例外——你正在使用它,所以我稍后会谈到。但是显示这些文件很棘手。使用它们更加困难。在我看来,git stash
前端需要在这里做一些工作。
不过,首先,了解 Git 内部是如何工作的很重要。Git存储库主要是一对数据库。一个——几乎总是最大的一个——包含提交和其他 Git 对象。一个较小的数据库包含名称:分支名称 like master
、标签名称 like v2.1
、远程跟踪名称 likeorigin/master
等等。分支名称和标签名称等是通用ref或reference的特定形式。一个 ref 持有一个 Git 哈希 ID,最常见的是一个提交哈希 ID。1
每个提交本身也可以保存一个或多个先前提交的哈希 ID。这些是提交的父母。对于普通(非存储)提交,这些通常形成一个很好的简单链:最后一个提交记住,作为它的父级,倒数第二个。倒数第二个提交会记住它的父节点——最后一个提交的祖父节点——而祖父节点会记住另一个父节点,依此类推。根据定义,具有两个父级的提交是合并提交。
因此,分支名称仅包含提交的哈希 ID,我们想说的是该分支 / on / 中的最后一次提交。多个名称可以选择相同的哈希 ID,和/或可以从某个分支通过从其尖端提交开始并向后工作来访问哈希 ID。因此,在 Git 中,提交通常位于多个分支上。
提交本身包含所有(跟踪的)文件的快照。Git 通过将跟踪的文件写入 Git 的索引,然后使用git write-tree
将文件写入内部树对象,然后git commit-tree
使用 写入提交对象,使用git write-tree
. 所以所有的提交都起源于索引。而且,根据定义,索引中的任何文件都会被跟踪。所以这让我们有点困惑。
1要求分支名称和远程跟踪名称仅包含提交哈希ID;标签名称更灵活。
藏匿处
特殊的 ref refs/stash
(如果存在)指向一个提交。那就是stash@{0}
提交。(它在 on up 中的 reflog 条目stash@{1}
也都指向一个提交。)因此,当存储存在时,它由提交组成。这些提交不在分支上:2它们是通过refs/stash
而不是找到的。
普通存储具有合并提交的形式,但实质不同。所做的是git stash
使用上述非常低级别的方法进行两次git write-tree
提交git commit-tree
。第一次这样的提交,基于你运行git stash save
or时索引中的任何内容git stash push
,很容易:git write-tree
已经只是写了索引中的任何内容,所以这两个命令放在一起,使这个索引提交,我称之为i
(并且git stash
文档调用I
)。
第二次提交比较棘手,但本质上,git stash
运行的是什么git add -u
(尽管没有实际使用git add -u
并因此在各种版本中引入错误git stash
,其中一些在某些情况下会产生错误的工作树提交)。这会更新索引,以便它保存所有跟踪的文件,因为它们在工作树中的状态。然后对你git write-tree
的git commit-tree
工作树做一个很好的快照,当然减去任何未跟踪的文件。
因为git stash
使用的是低级命令,它可以使工作树提交——我称之为w
——它选择的任何父集。i
它与双方以及HEAD
作为其两个父母一起做出此承诺:
...--o--o <-- branch (HEAD)
|\
i-w
i
提交看起来像任何普通提交,并且提交w
类似于合并。它实际上不是合并——它只是添加到索引中的工作树的快照——但它的第一个父级是当前分支的提示提交,第二个父级是 commit i
。
进行此存储后,git stash save
执行git reset --hard
, 以使您的索引和工作树匹配HEAD
。它HEAD
本身永远不会移动,未跟踪的文件不会被保存并且不受影响。
但是,当您执行git stash save -u
orgit stash save -a
时,Git 会进行第三次提交,我称之为u
. 第三次提交使用了一个索引,该索引清除了所有跟踪的文件,然后加载了部分或全部未跟踪的文件,就像git add --force
在特定文件名上一样。3 进入第三次提交的文件集取决于您是否使用-u
或-a
:-u
枚举未被忽略的未跟踪文件,并-a
枚举所有未跟踪文件,即使它们被忽略。Git 将这些文件复制到(嗯,一个)索引中并进行此u
提交,根本没有父级,在它做出最终w
提交之前。然后它作为它的第三个父项进行w
提交:u
...--o--o <-- branch (HEAD)
|\
i-w
/
u
因此,w^1
是分支顶端的提交,w^2
是索引提交i
,w^3
是u
提交。 w
继续类似于合并提交——这次是章鱼合并——但它的快照与任何两次提交的存储相同。
已u
提交,git stash save
或git stash push
现在从您的工作树中删除提交中的所有文件u
。如果其中的某些文件u
也被忽略,它们仍会被删除。
如果 Git 无法将u
提交提取到您当前的工作树中,则应用三提交存储会失败。因此,了解第三次u
提交中的内容绝对有用。但是没有git stash ____
(用动词填空)来显示提交是否u
存在,更不用说其中的内容了。因此,我们必须依靠较低级别的 Git 命令。
特别是,因为u
是根提交,git show
所以会将它与空树进行比较。如果您不想要完整的差异,您可以使用git show --name-only
或获取文件列表。git ls-tree -r
要命名commit u
,我们可以命名任何 stash 提交——由它w
指向的任何提交对象refs/stash
或它的 reflog 条目之一——并添加^3
后缀以表示第三父级。如果存储只有w
and i
,^3
则将失败:没有第三个父母,因此没有什么可显示的。
2如果你愿意,你可以把它们放到一个树枝上,但结果是......充其量是丑陋的。
3在内部,git stash
使用临时索引而不是真实/主索引,使这更容易。它也为w
提交做到这一点。虽然有一个特殊的索引,即跟踪您的工作树的索引,但您可以随时创建一个临时索引,将其路径名放入GIT_INDEX_FILE
中,然后将 Git 命令与该临时索引一起使用,而不是使用区分索引。这对于需要创建提交的任何命令(需要使用索引)都非常方便,并且不想在过程中干扰索引。
推荐阅读
- javascript - 如何使用物化 css 将移动折叠 navarro 添加到 django?
- r - 使用阶跃函数的最大似然估计
- ios - 从“TCHMessageType”转换为不相关类型“String”总是失败
- python - Python 中是否有“可添加”协议或抽象基类?如果不是,如何定义它?
- algorithm - 动态规划:为什么以相反的顺序更新数组
- sql - 忽略 SQL 查询中的重复数据 ID?
- google-apps-script - 谷歌电子表格中的订单表按创建日期
- amazon-web-services - ECS 任务。如何在容器中使用 AWS CLI
- javascript - express js get方法后浏览器选项卡不断加载
- amazon-web-services - 亚马逊 ec2 是否有适用于亚马逊计算节省计划的 API?