삭제 된 줄을 어떻게“비난”합니까?


506

git blame수정 및 추가 된 줄에 좋지만 이전의 특정 커밋에 존재하는 줄이 결국 삭제 된 시점을 어떻게 알 수 있습니까? 나는 생각 bisect하고 있지만 더 편리한 것을 기대하고 있었다.

(당신이하기 전에 :이 경우, 난 그냥했다 git log -p및 코드 라인을 위해를 통하여 검색의 (a) 어떤 바보가 있었다 단지 내가 그 바보했다) B (이전 커밋에서 중요한 라인을 삭제.)


4
병합 중에 충돌을 제거 하고 싶 거나 (충돌) 표시 하기 위한 답 이있는 후속 조치 가 있습니다.git log -S<string> /path/to/file-c-cc
cfi

3
그것은해야 -c하고 --cc. @Steen : 맞습니다. 지적 해 주셔서 감사합니다! 어리석은 감독. 댓글을 편집 할 수 있으면 좋겠습니다. 광산을 삭제 한 후, 새로운 하나를 추가, 당신은 너무 :) 같아요 복잡 당신을 삭제
CFI

4
git blame삭제 된 줄과 함께 삭제 된 줄 ( 취소 선 또는 빨간색 텍스트 포함) 을 표시하는 옵션을 원합니다 .
Craig McQueen

쓰기 어려울까요? 나는 Git 내부에 대해 많이 모른다.
Malvolio

답변:


636

줄의 내용을 알고 있다면 다음과 같은 경우에 이상적인 사용 사례입니다.

git log -S <string> path/to/file

해당 문자열의 인스턴스를 소개하거나 제거하는 커밋을 보여줍니다. -G<regex>정규 표현식과 동일한 기능을 수행하는 것도 있습니다 ! 자세한 내용 man git-log-G-S옵션 또는 pickaxe (이 기능의 이름)를보고 검색하십시오.

-S옵션은 실제의 헤더에서 설명한 git-blame것이 사용 예를 보여주고 설명 섹션에서,도 맨 git log -S....


Brilliant ...이 포팅 작업에서 내가 필요한 것은 +1
jkp

37
1 년 이상 Git을 사용한 후에도 Git은 항상 내가 가진 거의 모든 사용 시나리오를 처리 할 수있는 명령 / 옵션을 가지고 있다는 사실에 놀랐습니다 . 이것을 공유해 주셔서 감사합니다. 바로 지금 필요한 것입니다!
Pascal Bourque

22
이 방법은 이전에 효과가 있었지만 지금은 행이 삭제 된 커밋을 찾지 못한 경우를 보았습니다. 문제의 행이 병합 커밋에서 삭제 된 것으로 나타났습니다. 실패한 이유는 무엇입니까? ( git blame --reverse방법은 그것을 찾았습니다.)
antinome

9
@antinome 병합에서 커밋을 표시하려면 -c옵션을 추가로 사용하십시오 .
yunzen

2
맨 페이지의 "-s"에서 ctrl + f를 수행했지만 아무것도 찾지 못했습니다. 페이지 어디에서 볼 수 있습니까 ?? git 1.8.5.2를 사용하고 있습니다.
temporary_user_name

134

당신이 정말로 원하는 것은

git blame --reverse START..END filename

에서 맨 페이지 :

뒤로가 아니라 앞으로 걸어가십시오. 선이 나타난 개정을 표시하는 대신 선이 존재하는 마지막 개정을 표시합니다. 이것은 비난의 경로가 START에 존재하는 START..END와 같은 다양한 수정이 필요합니다.

을 사용하면 git blame reverse행이 표시된 마지막 커밋을 찾을 수 있습니다. 여전히 커밋을 가져와야합니다.

다음 명령을 사용하여 반전 된 자식 로그를 표시 할 수 있습니다. 표시된 첫 번째 커밋은 해당 줄이 마지막으로 나타나는 시간이며 다음 커밋은 변경되거나 제거 될 때입니다.

git log --reverse --ancestry-path COMMIT^..master

14
라인이 누락 된 분기에 라인이 추가 된 분기 (또는 START에서 END까지의 계보에 경로가 여러 개있는 다른 분기)에서 여러 개의 git blame --reverse병합이있는 경우 시간순으로 병합 이전의 개정을 표시합니다. 마지막으로, 라인을 취하지 않기로 결정한 초기 병합 이전의 개정이 아닙니다. 라인이 가장 최근 버전이 아닌 기존 라인을 중지 한 가장 빠른 버전을 찾는 방법이 있습니까?
rakslice

2
@rakslice, 당신은 비난을 사용할 수 있기 때문에 --reverse --first-parent, 그것은 조금 낫습니다.
max630

17

Cascabel의 답변 을 완성하는 :

git log --full-history -S <string> path/to/file

여기에 언급 된 것과 같은 문제가 있었지만 지점의 병합 커밋이 되돌려지고 다시 병합되어 문제의 줄을 효과적으로 제거했기 때문에 줄이 누락 된 것으로 나타났습니다. --full-history플래그 방지는 그 커밋을 건너 뛰는.


9

git blame --reverse 를 사용 하면 줄이 삭제 된 위치에 가까이 수 있습니다 . 그러나 실제로 행이 삭제 된 개정을 가리 키지 는 않습니다 . 마지막을 가리킨다 라인이었다 개정 존재 . 그런 다음 다음 개정판 이 일반 커밋이면 운이 좋으며 삭제 개정판을 얻습니다. OTOH, 다음 개정판이 merge commit 인 경우 상황이 약간 나빠질 수 있습니다.

difflame 을 만들려는 노력의 일환으로 나는이 문제를 해결 했으므로 이미 상자에 Python이 설치되어 있고 시도해보고 싶다면 더 이상 기다리지 말고 어떻게 진행되는지 알려주십시오.

https://github.com/eantoranz/difflame


0

병합 커밋에 숨겨진 변경 사항

병합 커밋은 변경 사항을 Git 로그 출력에서 ​​자동으로 숨 깁니다. 곡괭이후진은 모두 변화를 찾지 못했습니다. 그래서 내가 원하는 줄이 추가되고 나중에 제거되었고 그것을 제거 한 병합을 찾고 싶었습니다. 파일 git log -p -- path/file히스토리가 추가 된 것만 보여주었습니다. 내가 찾은 가장 좋은 방법은 다음과 같습니다.

git log -p -U9999 -- path/file

변경 사항을 검색 한 후 "^ commit"을 역방향으로 검색하십시오. 첫 번째 "^ commit"은 파일의 마지막 행이 커밋 된 것입니다. 두 번째 "^ commit"은 사라진 후입니다. 두 번째 커밋은 제거한 것일 수 있습니다. 그만큼-U9999 파일 모두 최대 9999 선입니다 가정 (파일이 변경 될 때마다 후) 전체 파일 내용을 표시하기위한 것입니다.

무차별 대입을 통해 관련 병합을 찾습니다 (가능한 모든 병합 커밋을 첫 번째 상위와 비교하고 많은 커밋에 대해 실행)

git log --merges --pretty=format:"git diff %h^...%h | grep target_text" HEAD ^$(git merge-base A B) | sh -v 2>&1 | less

(수정 필터를 더 제한하려고 시도했지만 문제가 발생하여 권장하지 않습니다. 내가 찾고 있던 추가 / 제거 변경 사항은 다른 시간에 병합 된 다른 지점에 있었으며 A ... B에는 포함되지 않았습니다. 변경 사항이 실제로 메인 라인에 병합 된 시점)

이 두 커밋으로 Git 트리 표시 (그리고 많은 복잡한 Git 히스토리가 제거되었습니다) :

git log --graph --oneline A B ^$(git merge-base A B) (A는 위의 첫 번째 커밋, B는 위의 두 번째 커밋)

A의 역사와 B의 역사를 빼고 A와 B의 역사를 뺀다.

대체 버전 (일반적인 Git 히스토리 트리보다는 경로를보다 선형으로 표시하는 것으로 간주되지만 일반 git 히스토리 트리를 선호합니다) :

git log --graph --oneline A...B

두 개의 점이 아닌 세 개의 점-세 개의 점은 "r1 r2-$ (git merge-base --all r1 r2가 아님)를 의미합니다. 이것은 r1 (왼쪽) 또는 r2 (오른쪽) 중 하나에서 도달 할 수있는 커밋 세트입니다. "하지만 둘 다가 아닙니다." -출처 : "man gitrevisions"

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