log - 如何在存儲庫中搜索特定字符串的所有Git和Mercurial提交?




search (9)

我有一個Git倉庫,只有很少的分支和懸而未決的提交。 我想在存儲庫中搜索所有這樣的提交以獲取特定的字符串。

我知道如何獲得歷史記錄中的所有提交記錄,但這些記錄不包括分支或懸空斑點,只是HEAD的歷史記錄。 我想讓他們都找到,找到一個錯誤的具體提交。

我還想知道如何在Mercurial中執行此操作,因為我正在考慮切換。


Answers

用Mercurial你可以做一個

$ hg grep "search for this" [file...]

還有其他選項可縮小搜索的修訂範圍。


在Mercurial中,您使用hg log --keyword搜索提交消息中的關鍵字,並使用hg log --user來搜索特定用戶。 請參閱hg help log以了解限制hg help log的其他方法。


除了使用git log -g --grep=<regexp>git grep -e <regexp> $(git log -g --pretty=format:%h) :請看看以下博客文章由當前的git維護者Junio C Hamano完成

概要

git grepgit log --grep都是面向行的 ,因為它們查找與指定模式匹配的行。

你可以使用git log --grep=<foo> --grep=<bar> (或者git log --author=<foo> --grep=<bar> ,內部翻譯成兩個--grep )來找到提交匹配一模式(隱式語義)。

由於面向行,所以有用的AND語義是使用git log --all-match --grep=<foo> --grep=<bar>來查找同時具有第一行和第二行匹配的提交

使用git grep你可以將多個模式(所有必須使用-e <regexp>形式的模式)與 - --or (這是默認設置), --and--or()組合在一起。 對於grep --all-match意味著文件必須具有匹配每個備選項的行。


基於rq的答案,我發現這條線符合我的要求:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

它會報告提交ID,文件名,並顯示匹配的行,如下所示:

91ba969:testFile:this is a test

...有沒有人同意,這將是一個很好的選擇,包括在標準的git grep命令中?



任何以引用為參數的命令都會接受git rev-list手冊頁中記錄的--all選項,如下所示:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

因此,例如git log -Sstring --all將顯示提及string所有提交,並且可以從分支或標記訪問(我假設您的懸掛提交至少用標記命名)。


為了添加更多尚未提及的解決方案,我不得不說,使用gitg的圖形搜索框對我來說是最簡單的解決方案。 它會選擇第一個匹配項,然後用Ctrl-G找到下一個匹配項。


不知道git,但是在Mercurial中,我只是將輸出的hg日誌輸出到某個sed / perl /腳本中,以搜索您要查找的任何內容。 如果您願意,您可以使用模板或樣式自定義hg日誌的輸出,以便於搜索。

這將包括回購協議中的所有命名分支。 Mercurial沒有像晃動blob afaik之類的東西。


這很大程度上取決於“恢復”的含義。

暫時切換到其他提交

如果你想暫時回到它,傻瓜,然後回到你所在的位置,你所要做的就是檢查所需的提交:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

或者,如果你想在那裡做出提交,那麼在你做的時候繼續做一個新的分支:

git checkout -b old-state 0d1d7fc32

要回到原來的位置,只需查看您再次訪問的分支。 (如果你做了更改,就像轉換分支時一樣,你必須在適當的時候處理它們。你可以重置它們扔掉它們;你可以藏匿,結賬,存放pop以帶走它們;你可以提交如果你想要那裡的分支,他們到那裡的一個分支。)

硬刪除未發布的提交

另一方面,如果你想真正擺脫自那時以來所做的一切,那麼有兩種可能性。 一,如果您還沒有發布任何這些提交,只需重置:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

如果你陷入困境,你已經拋棄了你的本地變化,但你至少可以通過重新設置來回到原來的位置。

使用新提交撤消已發布的提交

另一方面,如果您已發布作品,則可能不希望重置分支,因為這有效地重寫了歷史記錄。 在這種情況下,您確實可以還原提交。 使用Git,revert有一個非常具體的含義:使用反向補丁創建一個提交以取消它。 這樣您就不會重寫任何歷史記錄。

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

git-revert實際上在其描述中涵蓋了很多內容。 另一個有用的鏈接是這個討論git-revert的git-scm.com部分

如果您決定不想還原,則可以還原還原(如此處所述)或重置為還原之前(請參閱上一節)。

在這種情況下,您可能會發現此答案很有用:
如何將HEAD移回以前的位置? (獨立頭)





git mercurial