在存储代码后出现的“WIP”和“index”提交是什么?

16

当我在本地开发分支上运行git lg时,最新的提交如下所示:

* 7d21213 - (1 hours ago) update business rules - developer1 (HEAD, origin/develop, origin/HEAD, develop)

然而,如果我运行git stash来隐藏本地更改,然后运行git lg,我会得到以下内容:


*  at12334 - (13 seconds ago) WIP on develop: 7d21213 update business rules - developer1 (refs/stash)
|\
| * ef9a11b - (14 seconds ago) index on develop: 7d21213 update business rules - developer1
|/
* 7d21213 - (1 hours ago) update business rules - developer1 (HEAD, origin/develop, origin/HEAD, develop)

这是什么意思?看起来在存储后创建了两个新的提交(标记为indexWIP)。 如果是这样,那么背后的逻辑是什么?


注意

git lg

is an alias already defined in the test environment as

git log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)' --all
2个回答

15
"WIP"是工作正在进行的缩写。它旨在表明您正在临时保存当前工作状态,即使您没有到达自然停止点。
存储使用熟悉的提交/合并机制将您的工作保存在代码库中。特别地,可以通过运行gitk --reflog查看所有当前存储的项目的上下文,尽管只有最近的存储会带有stash标签。常规提交和存储之间的一个重要区别是,当存储被删除(例如通过git stash clear),它们在reflog中不再可见,因此将更难以恢复。
存储通常分为两个部分:
  1. 对自上次提交以来已经"add"的任何内容执行"索引"提交。
  2. "WIP"提交是在工作状态和索引提交之间进行合并。
如果你在上一次提交后没有执行任何add操作,索引提交将为空。但是,即使索引为空,它仍然被提交了。如果您想从一个存储中挑选出某些内容以避免与git stash pop相关的某些问题,则随后的隐式合并可能会使事情复杂化。 阅读更多
Git的存储机制非常聪明,强大和有用,但它也很复杂、容易出错和危险。最近我的做法是避免使用git stash,而是使用类似git commit -a -m "stash"的方法来保存我的工作,并使用git reset HEAD~1(在检出"stash"提交后)来恢复它,以获得类似的结果。
这样做留下了git stash最有用的应用程序,即成为一种快速摆脱所有本地更改的方法,如果您知道您不再需要它们。
顺便说一句,您可以通过运行git stash clear来从日志中删除"WIP"和"index"提交,但是如果您只在stash上保存了有价值的工作,请不要这样做

2
一个有价值的使用场景是使用stash在你rebase/merge上游变更时暂存正在进行中的工作,因为git不允许在你有未完成的更改时进行rebase。 - Brent Bradburn
有时候你回来后希望能够给自己的帖子点赞。git commit -a -m“WIP”的'+1'是git stash的更好替代品。 - Brent Bradburn
git stash可以在rebase期间非常有用--以便您想要回溯一点进行评估、测试并且重新排列早期提交。我不知道是否有其他替代方法可以复制git stash在此场景中的功能。 - Brent Bradburn
在检查“stash”提交之后,你的意思是什么? - rvcristiand
@rvcristiand:我在这里加上引号是因为它指的是我的“模拟”stash(提交信息为“stash”)-而不是实际的“git stash”,我避免使用它。您可以检出特定的提交-最好的方法通常是检出指向该提交的分支。重点是,git stash是一个方便的工具,可以使用正常的提交/检出机制轻松模拟它(这可能更安全)。 - Brent Bradburn

12

git lg是什么?

请注意,lg不是Git的原生命令。确实,许多人使用一个别名叫做lg,通常对应于


git log --all --oneline --graph --decorate

这个定义似乎是您在这里使用的那个。但是,别名是本地的;在您的配置中,git lg 的含义可能与在 Bob 和 Alice 的配置中的含义不同。

因此,您应该始终在问题中包含相关别名的定义,以便我们(Stack Overflow 用户)与您站在同一起点,并确切地知道运行时会发生什么。

git <alias>

在这里可以使用git lg命令查看详细的提交历史记录。

神秘物体是什么

这在git-stash手册讨论部分中有解释:

一个存储状态的快照(stash)表示为一次提交,其树记录了工作目录的状态,它的第一个父提交是创建存储状态快照的时刻 HEAD 所指向的提交。第二个父提交的树则记录了创建存储状态快照时的索引状态,并将其作为 HEAD 提交的子节点。祖先图看起来像这样:

       .----W
      /    /
-----H----I

其中HHEAD提交,I是记录索引状态的提交,W是记录工作树状态的提交。

对于您的情况:

  • 短SHA为ef9a11b的对象对应于索引状态(上图中的I),
  • 短SHA为at12334的对象对应于您的工作目录状态(上图中的W)。

这两个对象(WI)通常不会在git log的输出中列出,但如果使用--all标志,则会列出它们。


1
感谢您的回复,我已根据您的建议对问题进行了改进。您是否有进一步的解释,为什么需要记录索引的状态?在存储后,工作树的状态会发生变化,为了能够恢复它,我们需要保留它,这没问题。但是,索引也会发生变化吗?此外,存储可以在一周和多个提交之后弹出。恢复索引真的很重要吗? - clockworks
你需要为索引记录一个独特的对象,因为索引的状态不一定对应于工作树的状态。例如,您可以对文件进行本地修改,将这些更改暂存(将它们添加到索引中),然后进行更多修改,但不将其暂存;此时工作树和索引将不同。至于为什么要保存索引的状态(以及工作树的状态)...也许为下一次提交暂存文件是一项非常细致而繁琐的任务,您不想从头开始。 - jub0bs
如果在文件A中添加了两行并将更改添加到索引中,然后再添加了两行到同一文件中。我们可以说一半的更改存储在工作树中,另一半存储在索引中。因此,在stash之后恢复文件,需要同时存储索引和工作副本。 - clockworks
@stackr 是的,那就是想法。 - jub0bs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接