과거 언젠가 파일이나 파일의 일부 코드를 삭제했습니다. 내용에서 grep할 수 있습니까(커밋 메시지가 아님)?
매우 열악한 솔루션은 로그를 grep하는 것입니다.
git log -p | grep <pattern>
그러나 이것은 커밋 해시를 바로 반환하지 않습니다. 나는 git grep
으로 아무 소용이 없었습니다.
질문자 :Ortwin Gentz
과거 언젠가 파일이나 파일의 일부 코드를 삭제했습니다. 내용에서 grep할 수 있습니까(커밋 메시지가 아님)?
매우 열악한 솔루션은 로그를 grep하는 것입니다.
git log -p | grep <pattern>
그러나 이것은 커밋 해시를 바로 반환하지 않습니다. 나는 git grep
으로 아무 소용이 없었습니다.
커밋 내용 (즉, 커밋 메시지와 반대되는 실제 소스 줄)을 검색하려면 다음을 수행해야 합니다.
git grep <regexp> $(git rev-list --all)
git rev-list --all | xargs git grep <expression>
"인수 목록이 너무 깁니다" 오류가 발생하면 작동합니다.
검색을 일부 하위 트리(예: "lib/util")로 제한하려면 이를 rev-list
하위 명령과 grep
에도 전달해야 합니다.
git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util
regexp
대한 모든 커밋 텍스트를 grep합니다.
두 명령 모두에서 경로를 전달하는 이유는 rev-list
lib/util
대한 모든 변경 사항이 발생한 수정 lib/util
에서만 검색 grep
에 전달해야 하기 때문입니다.
다음 시나리오를 상상해 보십시오. grep
rev-list
의해 반환된 동일한 개정에 포함된 다른 파일 <regexp>
를 찾을 수 있습니다(해당 개정에서 해당 파일에 변경 사항이 없더라도).
소스를 검색하는 다른 유용한 방법은 다음과 같습니다.
정규 표현식 regexp와 일치하는 텍스트 검색 작업 트리:
git grep <regexp>
정규식 regexp1 또는 regexp2와 일치하는 텍스트 줄에 대한 작업 트리 검색:
git grep -e <regexp1> [--or] -e <regexp2>
파일 경로만 보고하는 정규식 regexp1 및 regexp2와 일치하는 텍스트 행에 대한 작업 트리 검색:
git grep -l -e <regexp1> --and -e <regexp2>
정규식 regexp1과 일치하는 텍스트 행과 정규식 regexp2와 일치하는 텍스트 행이 있는 파일에 대한 작업 트리 검색:
git grep -l --all-match -e <regexp1> -e <regexp2>
텍스트 일치 패턴의 변경된 라인에 대한 작업 트리 검색:
git diff --unified=0 | grep <pattern>
정규 표현식 regexp와 일치하는 텍스트에 대한 모든 개정 검색:
git grep <regexp> $(git rev-list --all)
정규식 regexp와 일치하는 텍스트에 대해 rev1과 rev2 사이의 모든 개정을 검색합니다.
git grep <regexp> $(git rev-list <rev1>..<rev2>)
git log
의 곡괭이( -S
) 옵션을 사용해야 합니다.
Foo
를 검색하려면:
git log -SFoo -- path_containing_change git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change
자세한 내용은 Git 기록 - 키워드별로 잃어버린 줄 찾기를 참조하세요.
Jakub Narębski 는 다음과 같이 말했습니다.
이것은 <string>
의 인스턴스를 도입하거나 제거하는 차이점을 찾습니다 . 일반적으로 "'Foo'로 줄을 추가하거나 제거한 수정본"을 의미합니다.
--pickaxe-regex
옵션을 사용하면 문자열을 검색하는 대신 확장된 POSIX 정규식을 사용할 수 있습니다. 예( git log
): git log -S"frotz\(nitfol" --pickaxe-regex
Rob이 언급했듯이 이 검색은 대소문자를 구분합니다. 그는 대소문자를 구분하지 않고 검색하는 방법에 대한 후속 질문을 열었습니다.
내가 가장 좋아하는 방법은 git log
의 -G
옵션(버전 1.7.4에 추가됨)을 사용하는 것입니다.
-G<regex> Look for differences whose added or removed line matches the given <regex>.
-G
및 -S
옵션이 커밋이 일치하는지 확인하는 방식에는 미묘한 차이가 있습니다.
-S
옵션은 기본적으로 커밋 전후에 파일에서 검색이 일치하는 횟수를 계산합니다. 커밋은 이전 및 이후 카운트가 다른 경우 로그에 표시됩니다. 예를 들어 검색과 일치하는 행이 이동한 커밋은 표시되지 않습니다.-G
옵션을 사용하면 검색이 추가, 제거 또는 변경된 행과 일치하는 경우 커밋이 로그에 표시됩니다.이 커밋을 예로 들어 보겠습니다.
diff --git a/test b/test index dddc242..60a8ba6 100644 --- a/test +++ b/test @@ -1 +1 @@ -hello hello +hello goodbye hello
파일에 "hello"가 나타나는 횟수는 이 커밋 전후에 동일하기 때문에 -Shello
사용하여 일치하지 않습니다. hello
와 일치하는 행이 변경되었으므로 커밋은 -Ghello
사용하여 표시됩니다.
코드 변경 사항을 검색하려면(전체 기록에서 주어진 단어로 실제로 변경된 사항 참조) patch
모드로 이동하십시오. 다음을 수행하는 매우 유용한 조합을 찾았습니다.
git log -p # Hit '/' for search mode. # Type in the word you are searching. # If the first search is not relevant, hit 'n' for next (like in Vim ;) )
git log
는 특히 일치하는 항목이 많고 최근(관련) 변경 사항을 먼저 확인하려는 경우 모든 분기에서 텍스트를 검색하는 더 효과적인 방법이 될 수 있습니다.
git log -p --all -S 'search string' git log -p --all -G 'match regular expression'
이 로그 명령은 주어진 검색 문자열/정규식을 (일반적으로) 더 최근의 것부터 추가하거나 제거하는 커밋을 나열합니다. -p
옵션을 사용하면 패턴이 추가되거나 제거된 위치에 관련 diff가 표시되므로 컨텍스트에서 볼 수 있습니다.
찾고 있던 텍스트를 추가하는 관련 커밋(예: 8beeff00d)을 찾았으면 커밋이 포함된 분기를 찾습니다.
git branch -a --contains 8beeff00d
모든 버전, 모든 파일 (unix/linux)에서 검색:
git rev-list --all | xargs git grep <regexp>
XML 파일과 같이 지정된 일부 파일에서만 검색:
git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"
결과 줄은 다음과 같아야 합니다. 6988bec26b1503d45eb0b2e8a4364afb87dde7af:bla.xml: 찾은 줄의 텍스트...
git show
사용하여 작성자, 날짜 및 diff와 같은 추가 정보를 얻을 수 있습니다.
git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af
Jeet의 답변을 가져와 Windows에 적용했습니다( 이 답변 덕분에).
FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt
어떤 이유에서인지 이 정규식을 삭제한 실제 커밋은 명령 출력에 나타나지 않고 그 이전의 커밋 하나에 나타납니다.
단순화를 위해 GUI를 사용하는 것이 좋습니다. gitk - The Git 저장소 브라우저 . 꽤 유연하다
위/아래 화살표를 사용하여 결과를 탐색할 수 있습니다.
나는 당신의 자리에 있을 때마다 다음 명령줄을 사용합니다.
git log -S "<words/phrases i am trying to find>" --all --oneline --graph
설명:
git log
- 여기에 더 작성해야 합니다. 시간순으로 로그를 보여줍니다.-S "<words/phrases i am trying to find>"
- 파일(추가/수정/삭제)에 '<>' 기호 없이 찾으려는 단어/구가 있는 모든 Git 커밋을 보여줍니다.--all
- 모든 분기에서 시행하고 검색합니다.--oneline
- Git 로그를 한 줄로 압축합니다.--graph
- 시간순으로 정렬된 커밋의 그래프를 생성합니다.Sourcetree 에서 이 작업을 시도하는 다른 사람의 경우 UI에 직접 명령이 없습니다(버전 1.6.21.0 현재). 그러나 터미널 창(메인 도구 모음에서 사용 가능한 버튼)을 열고 거기에 복사/붙여넣기를 하면 수락된 답변에 지정된 명령을 사용할 수 있습니다.
참고: Sourcetree의 검색 보기는 부분적으로 텍스트 검색을 수행할 수 있습니다. Ctrl + 3 을 눌러 검색 보기로 이동합니다(또는 하단에 있는 검색 탭을 클릭). 맨 오른쪽에서 검색 유형을 파일 변경으로 설정한 다음 검색하려는 문자열을 입력합니다. 이 방법은 위의 명령에 비해 다음과 같은 제한 사항이 있습니다.
답변 https://stackoverflow.com/a/2929502/6041515 에서 영감을 받아 git grep
이 diff뿐만 아니라 각 커밋에서 전체 코드 기반을 검색하는 것으로 나타났습니다. 결과는 반복적이고 길었습니다. 아래의 이 스크립트는 대신 각 git 커밋의 diff만 검색합니다.
for commit in $(git rev-list --all); do # search only lines starting with + or - if git show "$commit" | grep "^[+|-].*search-string"; then git show --no-patch --pretty=format:'%C(yellow)%h %Cred%ad %Cblue%an%Cgreen%d %Creset%s' --date=short $commit fi done
예제 출력, 맨 아래 git 커밋은 내가 찾고 있는 변경 사항을 처음 도입한 것입니다.
csshx$ for commit in $(git rev-list --all); do > if git show "$commit" | grep "^[+|-].*As csshX is a command line tool"; then > git show --no-patch --pretty=format:'%C(yellow)%h %Cred%ad %Cblue%an%Cgreen%d %Creset%s' --date=short $commit > fi > done +As csshX is a command line tool, no special installation is needed. It may 987eb89 2009-03-04 Gavin Brock Added code from initial release
이미 존재하는 답변에 더 많은 것을 추가합니다. 만들 수 있는 파일을 알고 있는 경우 다음을 수행합니다.
git log --follow -p -S 'search-string' <file-path>
--follow: 파일의 히스토리를 나열합니다.
자, 오늘 두 번이나 hg grep
대해 더 가까운 것을 원하는 사람들을 보았습니다. 이는 git log -pS
와 비슷하지만 출력을 (주석이 있는) 변경된 행으로 제한합니다.
빠른 개요를 보고 싶다면 호출기에서 /pattern/
보다 더 편리할 것 같습니다.
git log --pretty=%h -p
출력을 취하고 주석이 달린 변경 라인을 뱉어내는 diff-hunk 스캐너가 있습니다. 그것을 diffmarkup.l
에 넣고, 예를 들어 make ~/bin/diffmarkup
과 같이 사용하십시오.
git log --pretty=%h -pS pattern | diffmarkup | grep pattern
%option main 8bit nodefault // vim: tw=0 %top{ #define _GNU_SOURCE 1 } %x commitheader %x diffheader %x hunk %% char *afile=0, *bfile=0, *commit=0; int aline,aremain,bline,bremain; int iline=1; <hunk>\n ++iline; if ((aremain+bremain)==0) BEGIN diffheader; <*>\n ++iline; <INITIAL,commitheader,diffheader>^diff.* BEGIN diffheader; <INITIAL>.* BEGIN commitheader; if(commit)free(commit); commit=strdup(yytext); <commitheader>.* <diffheader>^(deleted|new|index)" ".* {} <diffheader>^"---".* if (afile)free(afile); afile=strdup(strchrnul(yytext,'/')); <diffheader>^"+++".* if (bfile)free(bfile); bfile=strdup(strchrnul(yytext,'/')); <diffheader,hunk>^"@@ ".* { BEGIN hunk; char *next=yytext+3; #define checkread(format,number) { int span; if ( !sscanf(next,format"%n",&number,&span) ) goto lostinhunkheader; next+=span; } checkread(" -%d",aline); if ( *next == ',' ) checkread(",%d",aremain) else aremain=1; checkread(" +%d",bline); if ( *next == ',' ) checkread(",%d",bremain) else bremain=1; break; lostinhunkheader: fprintf(stderr,"Lost at line %d, can't parse hunk header '%s'.\n",iline,yytext), exit(1); } <diffheader>. yyless(0); BEGIN INITIAL; <hunk>^"+".* printf("%s:%s:%d:%c:%s\n",commit,bfile+1,bline++,*yytext,yytext+1); --bremain; <hunk>^"-".* printf("%s:%s:%d:%c:%s\n",commit,afile+1,aline++,*yytext,yytext+1); --aremain; <hunk>^" ".* ++aline, ++bline; --aremain; --bremain; <hunk>. fprintf(stderr,"Lost at line %d, Can't parse hunk.\n",iline), exit(1);
마지막으로 존재하는 위치를 확인하기 위해 이전 버전의 코드를 grep하려고 합니까?
이 작업을 수행했다면 아마도git bisect 를 사용했을 것입니다. bisect를 사용하면 알려진 좋은 버전, 알려진 나쁜 버전, 버전이 좋은지 나쁜지 확인하는 간단한 스크립트(이 경우 찾고 있는 코드가 있는지 확인하는 grep)를 지정할 수 있습니다. ). 이것을 실행하면 코드가 제거된 시점을 찾을 수 있습니다.
Jet의 답변 은 PowerShell에서 작동합니다.
git grep -n <regex> $(git rev-list --all)
password
가 포함된 모든 파일을 표시합니다.
# Store intermediate result $result = git grep -n "password" $(git rev-list --all) # Display unique file names $result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }
시나리오: IDE를 사용하여 코드를 크게 정리했습니다. 문제: IDE가 필요 이상으로 정리되었지만 이제 코드가 컴파일되지 않습니다(리소스 누락 등).
해결책:
git grep --cached "text_to_find"
"text_to_find"가 변경된 파일을 찾습니다.
이제 이 변경을 취소하고 코드를 컴파일할 수 있습니다.
git rev-list --all | xargs -n 5 git grep EXPRESSION
Jeet의 솔루션에 대한 조정이므로 검색하는 동안 결과가 표시되고 끝이 아니라(큰 저장소에서 시간이 오래 걸릴 수 있음) 표시됩니다.
출처 : http:www.stackoverflow.com/questions/2928584/how-to-grep-search-committed-code-in-the-git-history
... 값에 삽입( SELECT ... FROM ... ) (0) | 2022.01.14 |
---|---|
C++11에서 람다 표현식이란 무엇입니까? (0) | 2022.01.08 |
정의되지 않은 참조/해결되지 않은 외부 기호 오류는 무엇이며 어떻게 수정합니까? (0) | 2022.01.08 |
var 키워드의 목적은 무엇이며 언제 사용(또는 생략)해야 합니까? (0) | 2022.01.08 |
Mac OS X의 지정된 TCP 포트에서 누가 듣고 있습니까? (0) | 2022.01.08 |