Git을 사용하여 저장소에서 일치하는 파일 이름을 검색 할 수 있습니까?
Git 저장소의 여러 하위 디렉토리에 "HelloWorld.pm"파일이 있다고 말하면됩니다.
"HelloWorld.pm"과 일치하는 모든 파일의 전체 경로를 찾는 명령을 실행하고 싶습니다.
예를 들면 :
/path/to/repository/HelloWorld.pm
/path/to/repository/but/much/deeper/down/HelloWorld.pm
/path/to/repository/please/dont/make/me/search/through/the/lot/HelloWorld.pm
Git을 사용하여 주어진 파일 이름과 일치하는 모든 전체 경로를 효율적으로 찾는 방법은 무엇입니까?
Linux / Unix find 명령으로이 작업을 수행 할 수 있다는 것을 알고 있지만 파일 이름의 인스턴스를 찾는 모든 하위 디렉터리를 검색하는 것을 피하고 싶었습니다.
git ls-files
저장소에있는 모든 파일의 목록을 제공합니다. 패턴을 전달하여 해당 패턴과 일치하는 파일을 가져올 수 있습니다.
git ls-files '*/HelloWorld.pm'
파일 세트를 찾고 내용을 통해 grep하려면 다음을 사용하여 수행 할 수 있습니다 git grep
.
git grep some-string -- '*/HelloWorld.pm'
음, 원래 질문은 저장소에 관한 것이 었습니다. 저장소에는 두 개 이상의 커밋이 포함되어 있지만 (적어도 일반적인 경우) 검색 전에 제공된 답변은 하나의 커밋을 통해서만 제공됩니다.
전체 커밋 기록을 실제로 검색하는 답을 찾을 수 없었기 때문에 거의 모든 커밋을 고려하는 빠른 무차별 대입 스크립트 git-find-by-name을 작성했습니다.
#! /bin/sh
tmpdir=$(mktemp -td git-find.XXXX)
trap "rm -r $tmpdir" EXIT INT TERM
allrevs=$(git rev-list --all)
# well, nearly all revs, we could still check the log if we have
# dangling commits and we could include the index to be perfect...
for rev in $allrevs
do
git ls-tree --full-tree -r $rev >$tmpdir/$rev
done
cd $tmpdir
grep $1 *
더 우아한 방법이있을 수 있습니다.
매개 변수가 grep에 전달되는 사소한 방법에 유의하십시오. 따라서 파일 이름의 일부와 일치합니다. 이것이 원하지 않는 경우 검색 표현식을 앵커하거나 적절한 grep 옵션을 추가하십시오.
깊은 역사의 경우 출력이 너무 시끄러울 수 있습니다. git rev-list가 할 수있는 것과는 반대로 개정 목록을 범위로 변환하는 스크립트에 대해 생각했습니다. 그러나 지금까지 그것은 생각으로 남아 있습니다.
시험:
git ls-tree -r HEAD | grep HelloWorld.pm
git ls-files | grep -i HelloWorld.pm
grep -i는 grep 대소 문자를 구분하지 않습니다.
[이건 약간의 댓글 남용입니다. 인정하지만 아직 댓글을 달 수 없으며 @ uwe-geuder의 답변을 개선 할 것이라고 생각했습니다.]
#!/bin/bash
#
#
# I'm using a fixed string here, not a regular expression, but you can easily
# use a regular expression by altering the call to grep below.
name="$1"
# Verify usage.
if [[ -z "$name" ]]
then
echo "Usage: $(basename "$0") <file name>" 1>&2
exit 100
fi
# Search all revisions; get unique results.
while IFS= read rev
do
# Find $name in $rev's tree and only use its path.
grep -F -- "$name" \
<(git ls-tree --full-tree -r "$rev" | awk '{ print $4 }')
done < \
<(git rev-list --all) \
| sort -u
다시 한 번 @ uwe-geuder에 +1하여 훌륭한 답변을 얻으십시오.
BASH 자체에 관심이있는 경우 :
당신이 (이 같은 배열을 사용할 때 같이 for 루프의 단어 분할의 보장하지 않는 한 for item in "${array[@]}"
), 나는 높게 사용하는 것이 좋습니다 while IFS= read var ; do ... ; done < <(command)
당신이 이상 반복하고 명령 출력은 줄 바꿈 (또는에 의해 분리 될 때 read -d''
출력에 의해 분리 될 때 null 문자열 $'\0'
). git rev-list --all
40 바이트 16 진수 문자열 (공백 없음)을 사용 하는 것이 보장 되지만 기회를 잡는 것을 좋아하지 않습니다. 이제 git rev-list --all
명령을 라인을 생성 하는 명령으로 쉽게 변경할 수 있습니다.
또한 기본 제공 BASH 메커니즘을 사용하여 임시 파일 대신 입력 및 필터 출력을 주입하는 것이 좋습니다.
The script by Uwe Geuder (@uwe-geuder) is great but there really is no need to dump each of the ls-tree outputs in its own directory, unfiltered.
Much faster and using less storage: Run the grep on the output and then store it, as shown in this gist
'development' 카테고리의 다른 글
C에서 32 비트 정수를 선언하는 방법 (0) | 2020.11.07 |
---|---|
실시간으로 텍스트 파일을 모니터링하는 방법 (0) | 2020.11.06 |
비동기 메서드가 값을 반환하도록하는 방법은 무엇입니까? (0) | 2020.11.06 |
실용적인 스타일의 실용적인 용도는 무엇입니까? (0) | 2020.11.06 |
LLVM / Clang을 사용하여 특정 파일의 모든 경고 무시 (0) | 2020.11.06 |