我如何通过关键字在GIT存储库中找到无法访问的提交哈希? [英] How can I find an unreachable commit hash in a GIT repository by keywords?
问题描述
我正在开发一个GIT版本化的项目,我刚刚注意到我们认为已经有一些提交在几个星期前的主分支实际上是失踪。我记得这些提交是由别人在功能分支功能/某些东西上推动的,而这些功能并不存在。
我试图找到那些缺少的提交来修复我们错误并将它们推到永久分支上
在这个团队中,每个开发人员都将他正在工作的票据的ID放入提交消息中,所以我知道肯定的票证ID(例如1234)是
在我正在寻找的提交消息中,所以我试过:
git log --all --grep = 1234
git log -g --grep = 1234
git log --all | grep 1234
git reflog | grep 1234
所有这些命令都没有返回任何内容。
此时,我正要放弃,然后我想起了我们的git repo与Slack集成在一起,所以我在懒散的历史记录
中搜索了1234,并发现了提交哈希值,我马上试过:
git show hash1
git show hash2
编辑所有提交信息。所以提交在那里,不知何故仍然在我的本地存储库。
所以我想仔细检查我是如何错过它们的:
git reflog | grep hash1
git分支--contains hash1
git fsck --lost-found | grep hash1
无。
git fsck --unreachable | grep hash1
unreachable commit hash1
这里是它在无法访问的提交列表中。
但是这是一个很大的项目,并且 git fsck --unreachable
返回一大堆提交,我怎么能找到这失去了关键字提交?
如果我们没有第三方工具记录git活动,也许我会试着将git fsck的输出重新映射回git show
并对结果进行精简,但这似乎很重要PS:我很抱歉无法分享回购协议,这是一个私人项目,但以下内容仅供参考。应该重现的情况:
用户A:
git clone< ;回购>
git checkout -b特性/某事
#添加一些内容提交
git commit -m特殊关键字
git push原点功能/某事
用户B:
git克隆< repo>
git push origin:feature / something
然后尝试查找由用户A推送的提交special-keyword。
你还要删除它的reflog。 HEAD
有一个单独的reflog,它会保留对已删除分支上的提交的引用,但只有当你拥有它们
- 找不到的
和 > - 无法访问
很微妙: 1 请参阅 git词汇表和/或下面的插图。一般情况下,使用 - lost-found
和/或 - unre achable
会找到这样的提交(并且使用 - lost-found
),并将ID写入 .git / lost-found / commit
目录,我认为具有防止垃圾回收的副作用)。
在这种特殊情况下,您正在查找的提交不是已删除分支的提示最多的提交。也就是说,在删除 feature / something
之前,假设在功能分支上进行了两次最新的提交:
A < - B < - C < - 主
\
D < - E < - 特征/某物
现在我们删除 feature / something
,丢失ID的提交 E
和 D
两者。这两个ID将显示在 git fsck --unreachable
的输出中,但只有 E
的ID会显示出来(并保存) git fsck --lost-found
,因为commit D
从 E
如果/当您恢复该提交时。
寻找您的提交
我怎么能通过关键字找到这个丢失的提交?
这有点棘手。可能你最好的选择是在所有无法访问的提交中使用 git show
,例如:
git show $(git fsck --unreachable | git cat-file --batch-check |
awk'/ commit / {print $ 3}')
现在您可以在日志消息(或差异)中搜索关键字(s)。内部的 $(...)
序列是提取所有候选ID的方法:我们只需要提交,而不是标签,树和blob。一旦你有了这些ID,可以使用所有常规的git命令( git log -1
, git show
等)与这些。
1 其实,我刚刚自己写了这个答案。
I'm a bit puzzled by a GIT situation.
I'm working on a GIT versioned project and I just noticed that some commits that we thought were already on the master branch weeks ago are actually missing. I remembered these commits were pushed by someone else on a feature branch "feature/something", which does not exist anymore.
I tried to find those missing commits to fix our mistake and to push them on a permanent branch. In this team, each developer puts the ID of the ticket he is working on in the commit message. So I know for sure ticket id (e.g 1234) is in the commit message I’m looking for, so I tried:
git log --all --grep=1234
git log -g --grep=1234
git log --all | grep 1234
git reflog | grep 1234
All of these commands returned nothing.
At this point, I was about to give up and then I remembered our git repo is integrated with Slack, so I searched 1234 in slack history and found the commits hashes. I immediately tried:
git show hash1
git show hash2
which surprisingly worked! It displayed all the commit information. So the commits are there, somehow still on my local repository. So I wanted to double check how I missed them:
git reflog | grep hash1
git branch --contains hash1
git fsck --lost-found | grep hash1
Nothing.
git fsck --unreachable | grep hash1
unreachable commit hash1
And here it is, in the unreachable commits list.
But this is a big project and git fsck --unreachable
returns a tons of commits, how could I have found this lost commit by keyword ?
If we did not have a third party tool logging the git activity, maybe I would have tried piping the output of git fsck back into git show somehow
and grepping on the result but that seems like a lot to do just to find a commit that I know is right here somewhere.
P.S: I’m sorry I can’t share the repo, it’s a private project but the following should reproduce the situation:
User A:
git clone <repo>
git checkout -b feature/something
# add something to commit
git commit -m "special-keyword"
git push origin feature/something
User B:
git clone <repo>
git push origin :feature/something
Now User B works for weeks, and then tries to find the commit "special-keyword" pushed by User A.
When you delete a branch, you also delete its reflog. There's a separate reflog for HEAD
that will retain a reference to commits that were on the deleted branch, but only if you've had them checked-out.
The difference between --lost-found
and --unreachable
is subtle:1 see the git glossary, and/or the illustration below. In general, using --lost-found
and/or --unreachable
will find such commit(s) (and with --lost-found
, also write IDs into the .git/lost-found/commit
directory, which I think has the side effect of protecting them from garbage collection).
In this particular case, the commit you were looking for was not the tip-most commit of the deleted branch. That is, suppose before deleting feature/something
we have this, with the two most recent commits made on the feature branch:
A <- B <- C <-- master
\
D <- E <-- feature/something
Now we delete feature/something
, losing the IDs of commits E
and D
both. Both IDs will show up in the output of git fsck --unreachable
, but only E
's ID will show up (and be saved) by git fsck --lost-found
, because commit D
is "reachable" from E
if/when you restore that commit.
Finding your commit
how could I have found this lost commit by keyword?
It's a bit tricky. Probably your best bet is using git show
on all unreachable commits, something like:
git show $(git fsck --unreachable | git cat-file --batch-check |
awk '/commit/ { print $3 }')
Now you can search for the keyword(s) in the log messages (or the diffs). The internal $(...)
sequence is the method for extracting all the candidate IDs: we just want commits, not tags, trees, and blobs. Once you have the IDs, all regular git commands (git log -1
, git show
, etc) can be used with those.
1In fact, I just learned it myself writing up this answer.
这篇关于我如何通过关键字在GIT存储库中找到无法访问的提交哈希?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!