특정 경로에 대한 변경 사항을 무시하는 'git log'만들기


121

git log지정한 파일이 아닌 다른 파일을 변경 한 커밋 만 표시하려면 어떻게 해야합니까?

을 사용하면 git log주어진 경로 집합에 닿는 커밋을 필터링 할 수 있습니다. 내가 원하는 것은 지정된 경로 이외의 터치 경로 만 나열되도록 해당 필터를 반전하는 것입니다.

나는 내가 원하는 것을 얻을 수있다

git log --format="%n/%n%H" --name-only | ~/filter-log.pl | git log --stdin --no-walk

어디에 filter-log.pl:

#!/usr/bin/perl
use strict;
use warnings;

$/ = "\n/\n";
<>;

while (<>) {
    my ($commit, @files) = split /\n/, $_;

    if (grep { $_ && $_ !~ m[^(/$|.etckeeper$|lvm/(archive|backup)/)] } @files) {
        print "$commit\n";
    }
}

나는 그것보다 다소 우아한 것을 원한다.

참고 나는 오전 없는 파일을 무시 GIT 만드는 방법을 물어. 이러한 파일 추적하고 커밋 해야 합니다. 대부분의 경우 나는 그들을 보는 데 관심이 없습니다.

관련 질문 : `git log --grep = <pattern>`반전 방법 또는 패턴과 일치하지 않는 git 로그를 표시하는 방법 경로가 아닌 커밋 메시지를 제외하고는 동일한 질문입니다.

2008 년 부터이 주제에 대한 포럼 토론 : Re : git-diff에서 파일 제외 이것은 유망 해 보였지만 스레드가 말라 버린 것 같습니다.


기본 제공 방법이 있는지 확실하지 않으며 펄 솔루션이 꽤 괜찮아 보입니다. 경로를 명령 줄 인수로 허용하도록 수정하는 경우, 같은 별칭을 만들 !f() { git log ... | path/to/filter-log.pl "$@" | git log --stdin --no-walk; f거나 파이프 라인 부분을 스크립트로 래핑 할 수도 있습니다.
Cascabel 2011

해결 방법 find으로 커밋을보고 싶지 않은 디렉터리를 필터링하는 데 사용 합니다. 루트 수준 디렉토리에 대한 커밋의 로그 항목을 무시하고 싶다면 SiteConfig다음과 같이 말합니다.git log `find . -type d -mindepth 1 -maxdepth 1 ! -name *SiteConfig`
Noah Sussman

Git 1.9 / 2.0 (2014 년 1 분기)의 경우 아래 내 답변을 참조하십시오 . git log --oneline --format=%s -- . ":!sub"작동합니다 ( pathspec 매직 :(exclude)및 짧은 형식 사용:! )
VonC

답변:


214

그것은 지금 소개와 (자식 1.9 / 2.0, Q1 2014) 구현 pathspec 마법 :(exclude)과 짧은 형식:!ef79b1f를 저지1,649,612을 투입 하여, 응웬 타이 응옥 두이 ( pclouds) , 문서를 찾을 수 있습니다 여기에 .

이제 하위 폴더 콘텐츠를 제외한 모든 항목을 기록 할 수 있습니다.

git log -- . ":(exclude)sub"
git log -- . ":!sub"

또는 해당 하위 폴더 내의 특정 요소를 제외 할 수 있습니다.

  • 특정 파일 :

      git log -- . ":(exclude)sub/sub/file"
      git log -- . ":!sub/sub/file"
    
  • 에서 주어진 파일 sub:

      git log -- . ":(exclude)sub/*file"
      git log -- . ":!sub/*file"
      git log -- . ":(exclude,glob)sub/*/file"
    

제외 대소 문자를 구분하지 않도록 설정할 수 있습니다!

git log -- . ":(exclude,icase)SUB"

케니 Evitt 지적

Bash 셸에서 Git을 실행하는 경우 ':!sub'또는 ":\!sub"대신 오류 를 피하십시오.bash: ... event not found


참고 : Git 2.13 (2017 년 2 분기)은 다음에 동의어 ^를 추가합니다.!

Linus Torvalds ( )의 commit 859b7f1 , commit 42ebeb9 (2017 년 2 월 8 일)를 참조하십시오 . (Merged by Junio ​​C Hamano -- in commit 015fba3 , 27 Feb 2017)torvalds
gitster

pathspec 매직 : ' ^'의 별칭으로 ' !'추가

!부정적인 경로 스펙에 대한 ' ' 의 선택은 우리가 수정을 위해하는 일과 일치하지 않을뿐만 아니라 인용이 필요하기 때문에 쉘 확장을위한 끔찍한 문자이기도합니다.

따라서 ^제외 pathspec 항목에 대한 대체 별칭으로 ' '를 추가 하십시오.


Git 2.28 (2020 년 3 분기) 이전에는 작업 트리에서 추적되지 않은 경로를 포함하여 경로를 수집하는 동안 음의 경로 지정을 사용하지 못했습니다.

Elijah Newren ( )의 commit f1f061e (2020 년 6 월 5 일)를 참조하십시오 . (Merged by Junio ​​C Hamano -- in commit 64efa11 , 18 Jun 2020)newren
gitster

dir: 부정 된 경로 스펙의 처리 수정

보고자 : John Millikin
서명자 : Elijah Newren

do_match_pathspec()삶을 시작했고 match_pathspec_depth_1()정확성을 위해에서 호출해야했습니다 match_pathspec_depth(). match_pathspec_depth()나중에로 이름이 변경 match_pathspec()되었으므로 오늘날 우리가 예상하는 불변성은 do_match_pathspec()외부에 직접 호출자가 없다는 것입니다 match_pathspec().

안타깝게도이 의도는 두 함수의 이름이 바뀌면서 사라졌으며do_match_pathspec() 커밋 75a6315f74 ( " ls-files: 하위 모듈에 대한 경로 지정 일치 추가", 2016-10-07, Git v2.11.0-rc0- 병합 목록에 추가 호출 이 추가되었습니다 . batch # 11 ) 및 89a1f4aaf7 ( " dir: 경로 사양이 dir 아래의 파일과 일치 할 수있는 경우 여기로 재귀", 2019-09-17, Git v2.24.0-rc0).

물론, do_match_pathspec()이상 중요한 advantge했다 match_pathspec()- match_pathspec()두 개의 값, 및 플래그에 대한 몇 가지 다른 값을 전달하는 데 필요한 새로운 호출자 중 하나에 플래그를 하드 것입니다.

또한 do_match_pathspec()직접 호출 하는 것은 정확하지 않지만 관찰 가능한 최종 출력에는 차이가 없었을 가능성이 큽니다. 버그는 단지 fill_diretory()불필요한 디렉토리로 재귀 한다는 것을 의미했기 때문 입니다.

이후 디렉토리 아래의 개별 경로에 대한이 경로 일치 검사를 수행하면 추가 경로가 필터링되기 때문에 잘못된 함수를 사용하는 것과의 유일한 차이점은 불필요한 계산이었습니다.

두 번째 잘못된 호출 do_match_pathspec()은 직접 이동 또는 복사 + 편집을 통해 이후의 여러 리팩터링에 포함되었습니다.

커밋 777b420347 ( " dir: 동기화 treat_leading_path()read_directory_recursive()", 2019-12-19, Git v2.25.0-rc0- merge ), 8d92fb2927 ( " dir: 지수 알고리즘을 선형 알고리즘으로 대체", 2020-04-01, Git v2.27.0 참조) -rc0- 병합배치 # 5에 나열 됨 ) 및 95c11ecc73 ( "오류가 발생하기 쉬운 fill_directory()API 수정 , 일치 항목 만 반환하도록 설정", 2020-04-01, Git v2.27.0-rc0- 배치 # 5에 나열된 병합 ) .

그 중 마지막은 do_match_pathspec()개별 파일에 대한 사용법을 소개 했기 때문에 반환되어서는 안되는 개별 경로가 반환되었습니다.

do_match_pathspec()대신 호출의 문제 match_pathspec()는 '`:! unwanted_path``와 같은 부정 된 패턴이 무시된다는 것 입니다.

match_pathspec_with_flags()부정한 패턴을 올바르게 검사하면서 특수 플래그를 지정해야하는 요구를 충족 하는 새 함수를 추가하고, do_match_pathspec()다른 사람이이를 오용하지 못하도록 위의 큰 주석을 추가하고 , do_match_pathspec()대신 match_pathspec()또는 을 사용하도록 현재 호출자를 수정 합니다 match_pathspec_with_flags().

마지막 DO_MATCH_LEADING_PATHSPEC으로 DO_MATCH_EXCLUDE.

요점은 DO_MATCH_LEADING_PATHSPEC다음과 같은 pathspec이있는 경우

*/Makefile

그리고 우리는 다음과 같은 디렉토리 경로를 확인하고 있습니다.

src/module/component

_might_ Makefile아래 어딘가에 이름이 지정된 파일이 있기 때문에 디렉토리로 재귀 할 수 있도록 일치 항목으로 간주하고 싶습니다 .

그러나 제외 패턴을 사용하는 경우, 즉, 다음과 같은 경로 지정이 있습니다.

:(exclude)*/Makefile

우리는 다음과 같은 디렉토리 경로를 말하고 싶지 않습니다.

src/module/component

(음수) 일치입니다.

이 동안 수도 디렉토리 아래의 '메이크'어딘가라는 이름의 파일 수, 다른 파일이있을 수 있으며, 우리는 예방 적-PRE OUT 디렉토리 아래의 모든 파일을 배제 할 수 없다; 재귀하고 개별 파일을 확인해야합니다.

DO_MATCH_LEADING_PATHSPEC긍정적 인 경로 사양에 대해서만 활성화 되도록 논리를 조정합니다 .


7
여러 파일을 할 수 있습니까?
Justin Thomas

12
@JustinThomas 나는 경로 제외 패턴을 여러 번 반복하여 ":(exclude)pathPattern1" ":(exclude)pathPattern2"여러 폴더 / 파일을 무시할 수 있다고 믿습니다 (아직 테스트되지 않았습니다) .
VonC 2014 년

7
Bash 셸에서 Git을 실행하는 경우 ':!sub'대신 사용하여 오류방지bash: ... event not found 하세요. ":\!sub"작동하지 않습니다.
Kenny Evitt

1
@KennyEvitt 귀하의 편집과 의견에 감사드립니다. 더 많은 가시성을 위해 답변에 후자를 포함했습니다.
VonC

2
이 기능에 대한 공식 문서가 어디에 있는지 궁금하신 분은 git help glossary( git help -g[내가 제안한 내용을 git help]에 나열되어 있음)을 참조하십시오 .
ravron

4

tl; dr : shopt -s extglob && git log !(unwanted/glob|another/unwanted/glob)

당신이 사용하는 경우 배쉬를 당신은 사용할 수 있어야 확장 로빙 필요한 파일 만 얻을 기능 :

$ cd -- "$(mktemp --directory)" 
$ git init
Initialized empty Git repository in /tmp/tmp.cJm8k38G9y/.git/
$ mkdir aye bee
$ echo foo > aye/foo
$ git add aye/foo
$ git commit -m "First commit"
[master (root-commit) 46a028c] First commit
 0 files changed
 create mode 100644 aye/foo
$ echo foo > bee/foo
$ git add bee/foo
$ git commit -m "Second commit"
[master 30b3af2] Second commit
 1 file changed, 1 insertion(+)
 create mode 100644 bee/foo
$ shopt -s extglob
$ git log !(bee)
commit ec660acdb38ee288a9e771a2685fe3389bed01dd
Author: My Name <jdoe@example.org>
Date:   Wed Jun 5 10:58:45 2013 +0200

    First commit

globstar재귀 작업 을 위해 이것을 결합 할 수 있습니다 .


7
더 이상 존재하지 않는 파일에 영향을 미치는 커밋은 표시되지 않습니다. 매우 가깝고 멋진 해킹이 모두 동일합니다.
Anonymoose 2013-06-05

-2

다음 을 사용하여 파일의 변경 사항을 일시적으로 무시할 수 있습니다 .

git update-index --skip-worktree path/to/file

해당 파일의 모든 변경 사항이 무시됩니다, 앞으로 git status, git commit -a당신이 그 파일을 커밋 할 준비가되면, 그냥 역 등 :

git update-index --no-skip-worktree path/to/file

정상적으로 커밋하십시오.


9
이것은 약간 다른 상황을 다루는 것으로 보입니다. 이미 작성된 커밋을 필터링 git update-index --skip-worktree하지 않습니다 git log.
Anonymoose 2011-07-07
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.