Git-메서드 / 함수의 변경 내역을 보려면 어떻게해야합니까?


93

그래서 파일의 변경 내역을 보는 방법에 대한 질문을 찾았지만이 특정 파일의 변경 내역은 엄청나고 특정 방법의 변경에만 관심이 있습니다. 특정 방법에 대한 변경 내역을 볼 수 있습니까?

나는 이것이 코드를 분석하기 위해 git이 필요하고 분석이 다른 언어에 따라 다를 것이라는 것을 알고 있지만 메소드 / 함수 선언은 대부분의 언어에서 매우 비슷해 보이므로 누군가이 기능을 구현했다고 생각했습니다.

현재 작업중인 언어는 Objective-C이고 현재 사용중인 SCM은 git이지만이 기능이 SCM / 언어에 대해 존재하는지 알고 싶습니다.


1
Git GSoG 제안에서 이러한 기능을 보았습니다.
Vi.

이것이 당신이 말하는 제안입니까? list-archives.org/git/…
Erik B


@lpapp 여기에있는 질문은 10 개월 전에 질문을 받았으며 다른 질문은이 질문의 속임수로 표시되어야합니다 (만약 속이는 경우).
더러운 흐름

2
@lpapp 이것들은 완전히 다른 두 가지 질문입니다. 함수 이름을 줄 범위로 확인하는 스크립트를 작성한 다음 해당 질문의 기술을 사용하여 해당 줄의 기록을 가져올 수 있지만 그 자체로는이 질문에 대답하지 않습니다.
Erik B

답변:


100

최근 버전의 git log학습 된 특수한 형태의 -L매개 변수 :

-L : <기능 이름> : <파일>

에서 제공하는 줄 범위 "<start>,<end>"(또는 함수 이름 regex <funcname>) 의 진화를 추적합니다 <file>. pathspec 제한자를 제공 할 수 없습니다. 이것은 현재 단일 개정에서 시작하는 걷기로 제한됩니다. 즉, 긍정적 인 개정 인수를 0 개 또는 1 개만 제공 할 수 있습니다. 이 옵션을 두 번 이상 지정할 수 있습니다.
...
만일이 “:<funcname>”대신에 부여 <start>하고 <end>는, 제 funcname에 줄의 범위를 나타내고, 일반 식된다 일치 <funcname>최대 funcname에 다음 라인. “:<funcname>”이전 -L범위 의 끝 (있는 경우)에서 검색하고 그렇지 않은 경우 파일 시작부터 검색합니다. “^:<funcname>”파일의 시작부터 검색합니다.

git log -L :myfunction:path/to/myfile.c, Git에게을 요청 하면 이제 해당 함수의 변경 내역을 기꺼이 인쇄합니다.


16
이것은 object-c에서 즉시 작동 할 수 있지만 다른 언어 (예 : Python, Ruby 등)에 대해이 작업을 수행하는 경우 git이 함수 / 메소드를 인식하도록 .gitattributes 파일 내에 적절한 구성을 추가해야 할 수 있습니다. 그 언어로 선언. 루비 사용하기위한 파이썬 사용 * 평은 diff = 파이썬, 들어 * .rb DIFF = 루비
samaspin

1
git은 함수를 어떻게 추적합니까?
nn0p

@ nn0p 여러 언어에 대한 구문 지식이 있고 함수를 분리하고 변경 사항을 추적하는 방법을 알고 있다고 가정합니다.
JasonGenX

4
: 당신이 여기에 문서를 참조 할 수 있습니다 다른 언어, samaspin의 코멘트 @ 확장 git-scm.com/docs/gitattributes#_generating_diff_text
edhgoose

이것은 Scala 및 Java와 같은 언어와 중첩 된 중괄호를 사용하는 C (정규식은 일반적으로 처리 할 수 ​​없음)에서는 작동하지 않으며 함수가 파일에서 이동 될 때 시작, 끝 양식도 작동하지 않습니다. 동일한 커밋에서 수정되었습니다.
Robin Green

16

사용은 git gui blame스크립트의 사용을 위해 열심히하고, 동안 git log -Ggit log --pickaxe방법 정의가 나타나거나 내가 그들에 대한 모든 변경 목록을 만들 수있는 방법을 발견하지 않은, 사라 때마다 당신을 보여줄 수있는 신체 당신의 방법을.

그러나 gitattributestextconv속성을 사용 하여이를 수행 하는 솔루션을 결합 할 수 있습니다 . 이러한 기능은 원래 바이너리 파일 작업을 돕기위한 것이지만 여기에서도 잘 작동합니다.

핵심은 Git이 diff 작업을 수행하기 전에 관심있는 행을 제외한 모든 행을 파일에서 제거하도록하는 것입니다. 그러면 git log, git diff등이 관심있는 영역 만 표시합니다.

다음은 제가 다른 언어로하는 일에 대한 개요입니다. 자신의 필요에 맞게 조정할 수 있습니다.

  • 하나의 인수 (소스 파일 이름)를 취하고 해당 파일의 흥미로운 부분 만 출력하는 짧은 쉘 스크립트 (또는 다른 프로그램)를 작성하십시오 (또는 흥미로운 부분이 없으면 아무것도 출력하지 않음). 예를 들어 sed다음과 같이 사용할 수 있습니다 .

    #!/bin/sh
    sed -n -e '/^int my_func(/,/^}/ p' "$1"
    
  • textconv새 스크립트에 대한 Git 필터를 정의하십시오 . (자세한 내용은 gitattributesman 페이지를 참조하십시오.) 필터 이름과 명령 위치는 원하는대로 지정할 수 있습니다.

    $ git config diff.my_filter.textconv /path/to/my_script
    
  • 문제의 파일에 대한 diff를 계산하기 전에 해당 필터를 사용하도록 Git에 지시하십시오.

    $ echo "my_file diff=my_filter" >> .gitattributes
    
  • 이제 -G.(참고 .)를 사용 하여 필터를 적용했을 때 눈에 띄는 변경 사항을 생성하는 모든 커밋을 나열하면 관심있는 커밋이 정확히 표시됩니다., 같은 Git의 diff 루틴을 사용하는 다른 옵션은 다음과 같습니다 --patch. 이 제한된보기도 얻을 수 있습니다.

    $ git log -G. --patch my_file
    
  • Voilà!

유용한 개선 사항 중 하나는 필터 스크립트가 메서드 이름을 첫 번째 인수로 사용하고 파일을 두 번째 인수로 사용하도록하는 것입니다. 이렇게하면 git config스크립트를 편집 할 필요 없이을 호출하여 관심있는 새 메서드를 지정할 수 있습니다 . 예를 들어 다음과 같이 말할 수 있습니다.

$ git config diff.my_filter.textconv "/path/to/my_command other_func"

물론, 필터 스크립트는 당신이 좋아하는 것을 할 수 있고, 더 많은 인수를 받거나, 무엇이든 할 수 있습니다. 제가 여기에서 보여준 것보다 훨씬 더 많은 유연성이 있습니다.


1
하나 이상의 인수를 가져가는 것은 저에게 효과가 없었지만 함수 이름을 열심히 작업하면 정말 훌륭합니다!
qwertzguy

훌륭하지만 많은 다른 방법을 전환하는 것이 얼마나 편리한 지 궁금합니다. 또한 전체 C와 유사한 기능을 끌어낼 수있는 프로그램을 알고 있습니까?
nafg

12

git log 에는 모든 차이점을 찾는 데 사용할 수있는 '-G'옵션이 있습니다.

-G 추가되거나 제거 된 행이 주어진 <regex>.

관심있는 함수 이름의 적절한 정규식을 제공하십시오. 예를 들면

$ git log --oneline -G'^int commit_tree'
40d52ff make commit_tree a library function
81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory
7b9c0a6 git-commit-tree: make it usable from other builtins

5
명령을 실행하지 않았지만이 명령은 전체 메서드 / 함수가 아닌 정규식과 일치하는 줄을 터치하는 커밋 만 표시하는 것처럼 보입니다.
Erik B

당신이 더 많은 컨텍스트를 원한다면, 당신은 대체 할 수 --oneline-p
lfender6445

3
그러나 방법에 20 줄을 변경하면 어떻게 될까요?
nafg

+1. 나를 위해 최고의 답변은 효과가 있었지만 가장 최근의 커밋 만 보여주었습니다. 아마도 리베이스 또는 기능이 몇 번 정도 이동했기 때문일 수 있습니다. 함수 대신 실제 코드 줄을 검색하여 (한 줄이지 만)이 답변을 사용하면 찾고 있던 커밋을 쉽게 찾을 수 있습니다. 고맙게도 저는 보통 유용한 커밋 메시지를 작성합니다!
Dave S

11

당신이 할 수있는 가장 가까운 일은 파일에서 당신의 함수의 위치를 ​​결정하는 것입니다 (예를 들어 당신의 함수 i_am_buggy가의 241-263 라인에 있다고 가정 해 봅시다 foo/bar.c), 그리고 다음의 효과를 위해 무언가를 실행하십시오 :

git log -p -L 200,300:foo/bar.c

이것은 덜 열릴 것입니다 (또는 동등한 호출기). 이제 입력 /i_am_buggy(또는 이에 상응하는 호출기)을 입력하고 변경 단계를 시작할 수 있습니다.

코드 스타일에 따라 작동 할 수도 있습니다.

git log -p -L /int i_am_buggy\(/,+30:foo/bar.c

이는 해당 정규식의 첫 번째 히트 (이상적으로는 함수 선언)에서 검색을 그 이후 30 행으로 제한합니다. end 인수는 regexp가 될 수도 있지만 regexp로 감지 하는 것은 iffier 제안입니다.


단! 참고로 이것은 Git v1.8.4의 새로운 기능입니다. (업그레이드해야한다고 생각합니다.) 더 정확한 솔루션이 좋지만 ... 누군가 Paul Whittaker의 대답을 스크립트로 작성하는 것과 같습니다.
Greg Price

@GregPrice 분명히 검색의 가장자리는 정규 표현식이 될 수도 있으므로 적어도 어느 정도 정확한 시작점을 가질 수 있습니다.
badp 2014

오 와우. 사실 : 자신 만의 정규식을 작성하는 대신 -L ":int myfunc:foo/bar.c"해당 이름으로 함수를 말하고 제한 할 수 있습니다 . 이것은 환상적입니다-포인터 주셔서 감사합니다! 기능 만 검출은 좀 더 신뢰할 수 있었다 이제 경우 ...
그렉 가격

3

올바른 방법은 eckes answer에git log -L :function:path/to/file 설명 된 대로 사용하는 것 입니다.

그러나 함수가 매우 긴 경우에는 이러한 행 중 하나만 터치 할 수있는 각 커밋에 대해 수정되지 않은 전체 기능 행이 아니라 다양한 커밋이 도입 한 변경 사항 만보고 싶을 수 있습니다. 평범한 것처럼 diff.

일반적으로 git log에서는 차이점을 볼 수 -p있지만에서는 작동하지 않습니다 -L. 따라서 grep git log -L컨텍스트 화하려면 관련된 라인과 커밋 / 파일 헤더 만 표시해야합니다. 여기서 트릭 --color은 정규식과 스위치를 추가하여 터미널 컬러 라인 만 일치 시키는 것입니다. 드디어:

git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3

참고 ^[문자, 실제이어야한다 ^[. bash에서 ^ V ^ [, 즉 Ctrl+ V, Ctrl+ 를 눌러 입력 할 수 있습니다 [. 여기를 참조 하십시오 .

또한 마지막 -3스위치를 사용하면 일치하는 각 줄 앞뒤에 3 줄의 출력 컨텍스트를 인쇄 할 수 있습니다. 필요에 따라 조정할 수 있습니다.


2

git blame 은 파일의 각 줄을 마지막으로 변경 한 사람을 보여줍니다. 검사 할 줄을 지정하여 함수 외부의 줄 기록을 가져 오지 않도록 할 수 있습니다.


4
함께 git gui blame당신은 이전 버전을 탐색 할 수 있습니다.
Vi.

0
  1. eckes의 답변git docgit log -L :<funcname>:<file>표시된 대로 함수 기록 표시

    아무것도 표시되지 않으면 사용자 정의 hunk-header 정의를 참조 하여 해당 언어를 지원 *.java diff=java하기 위해 .gitattributes파일에 유사한 항목을 추가 하십시오.

  2. 커밋 간 함수 기록 표시 git log commit1..commit2 -L :functionName:filePath

  3. 오버로드 된 함수 기록 표시 (이름은 같지만 매개 변수가 다른 함수가 많을 수 있음) git log -L :sum\(double:filepath

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.