git diff의 출력을 필터링하는 더 좋은 방법이 있습니까?

git diff의 출력을 필터링하는 더 좋은 방법이 있습니까?

SO 맥락에서 질문:git diff에서 변경된 줄 번호 찾기

위의 질문에 따라 git두 개정판 간의 수정된 파일의 차이점을 다음 형식으로 인쇄해야 합니다.

/path/to/file
startline1-startline2
startline3-startline4

/path/to/another/file
startline5-startline6
...

이 내 꺼야시도gitdiff의 출력을 필터링합니다 .

git diff --unified=0 --diff-filter=M HEAD~1 HEAD | \
grep -v -e '^[+-]' -e '^index' | \
sed 's/diff --git a.* b\//\//g; s/.*@@\(.*\)@@.*/\1/g; s/^ -//g; s/,[0-9]*//g; s/\(^[0-9]*\) +/\1-/g;'

git diff위 명령이 출력에 표시될 수 있는 모든 시나리오를 충족하는지 잘 모르겠습니다 .

awk기존 솔루션을 개선할 수 있습니까? 아니면 또는 그 자체 와 같은 다른 유틸리티를 사용하여 git이를 달성할 수 있는 더 좋은 방법이 있습니까?


기반으로답변주어진@murulu, 비교는 다음과 같습니다.

# Using git diff [expected output w.r.t line numbers and not formatting]

$ git diff --unified=0 --diff-filter=M HEAD~3 HEAD | grep -v -e '^[+-]' -e '^index'
diff --git a/lib/get-config.js b/lib/get-config.js
@@ -89,0 +90,5 @@ module.exports = {
diff --git a/lib/pull.js b/lib/pull.js
@@ -62 +62 @@ module.exports = class Pull {
@@ -83 +83 @@ module.exports = class Pull {
diff --git a/lib/router.js b/lib/router.js
@@ -3,0 +4 @@ const yaml = require('js-yaml')
@@ -125,0 +127 @@ module.exports = app => {
@@ -136,0 +139 @@ module.exports = app => {
# Using external diff as suggested by @muru
# [expected output with formatting but line numbers don't match with git diff's output]

$ git -c diff.external='./foo.sh' diff --diff-filter=M 'HEAD~3' HEAD
/tmp/AAAA_get-config.js
90-89

/tmp/BBBB_pull.js
62
83

/tmp/CCCC_router.js
4-3
126-125
137-136

파일의 줄 번호가 다릅니다 router.js.

저장소비교하려고.


출력에서 예상되는 형식을 명확히 하고 싶습니다.

git diff통합 diff 형식으로 출력을 생성합니다. 형식은 다음과 같습니다.

# Assumes --unified=0 i.e no context lines
diff --git a/path/to/file b/path/to/file
index x..z mode
--- a/path/to/file
+++ b/path/to/file
@@ -l1,s +l2,s @@ optional section heading
- ...
- ...
+ ...
+ ...
diff --git a/path/to/file1 b/path/to/file1
index y..z mode
--- a/path/to/file1
+++ b/path/to/file2
@@ -l3,s +l4,s @@ optional section heading
- ...
- ...
+ ...
+ ...
.
.
.

예상되는 출력에는 수정된 파일의 차이점(사용)만 포함되어야 하며 --diff-filer=M다음 형식이어야 합니다.

/path/to/file
l1-l2

/path/to/file1
l3-l4
l5-l6
.
.
.

여기서 l1, ...은 l2통합 diff 형식( ) @@ -l1,s +l2,s @@에서 언급된 줄 번호 입니다.


@murulu의 답변문제는 거의 해결되었으나 이렇게 변경된 그룹 형식을 사용하여 얻은 줄 번호가 '%df%(f=l?:-%dl)\n'통합 diff 형식의 줄 번호와 일치하지 않습니다.

와 같은 옵션을 사용하여 줄 번호(통합 diff 형식)를 표시하는 방법이 있습니까 changed-group-format?


이것은 MVCE를 사용하는 것입니다.bash git 저장소

사용 git diff,

$ git diff --unified=0 --diff-filter=M 9e49d ad1b3 | grep -v -e '^[+-]' -e '^index'
diff --git a/execute_cmd.c b/execute_cmd.c
@@ -567 +567 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
@@ -753,2 +753 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
@@ -759,2 +758 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
@@ -1104 +1102 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
diff --git a/patchlevel.h b/patchlevel.h
@@ -28 +28 @@
diff --git a/subst.c b/subst.c
@@ -5339 +5339 @@ clear_fifo_list ()
@@ -5345 +5345 @@ copy_fifo_list (sizep)
@@ -5411,7 +5411,2 @@ unlink_fifo_list ()
@@ -5433 +5428 @@ close_new_fifos (list, lsize)
@@ -5437 +5431,0 @@ close_new_fifos (list, lsize)
@@ -5445,2 +5439,2 @@ close_new_fifos (list, lsize)
@@ -5568 +5562 @@ clear_fifo_list ()
@@ -5572 +5566 @@ copy_fifo_list (sizep)
@@ -5578 +5572 @@ copy_fifo_list (sizep)
@@ -5583 +5577 @@ copy_fifo_list (sizep)
@@ -5656 +5650 @@ close_new_fifos (list, lsize)
@@ -5660 +5653,0 @@ close_new_fifos (list, lsize)
@@ -5668,2 +5661,2 @@ close_new_fifos (list, lsize)
diff --git a/subst.h b/subst.h
@@ -276,2 +276,3 @@ extern void unlink_fifo __P((int));

예상 출력

/execute_cmd.c
567-567 
753-753 
759-758 
1104-1102 

/patchlevel.h
28-28 

/subst.c
5339-5339 
5345-5345 
5411-5411 
5433-5428 
5437-5431 
5445-5439 
5568-5562 
5572-5566 
5578-5572 
5583-5577 
5656-5650 
5660-5653 
5668-5661 

/subst.h
276-276 

출력은 다음을 기반으로 합니다.@murulu의 답변

# Line numbers which don't match the expected output is indicated by "#"
$ git -c diff.external='../foo.sh' diff --diff-filter=M 9e49d ad1b3
/tmp/2wJaWf_execute_cmd.c
567
753-754 #
759-760 #
1104 #

/tmp/7j19Ob_patchlevel.h
28

/tmp/fQDY8b_subst.c
5339
5345
5411-5417 #
5433 #
5437 #
5445-5446 #
.
.
.

답변1

GNU diff를 사용한다면 다음과 같은 것을 얻어서 호출할 수 있습니다 git diff:

foo.sh

#! /bin/bash
# See https://stackoverflow.com/a/255212/2072269 for details on parameters
echo "$2" # print filename
diff --changed-group-format $'%df%(f=l?:-%dl)\n' --line-format='' "$2" "$5"
echo
exit 0

그리고 (예를 들어bash git 저장소):

$ export GIT_EXTERNAL_DIFF="$PWD/foo.sh"
$ git diff HEAD 'HEAD^^'
execute_cmd.c
567
753-754
759-760
1104

patchlevel.h
28

subst.c
5339
5345
5411-5417
5433
5437
5445-5446
5568
5572
5578
5583
5656
5660
5668-5669

subst.h
276-277

이것암소 비슷한 일종의 영양diff옵션:

--changed-group-format=체재
이러한 줄 그룹은 두 파일의 줄을 포함하는 블록입니다.

%df및 는 %dl이전 파일에 있는 변경 그룹의 f첫 번째 및 마지막 줄 번호(10진수) 입니다. 첫 번째 행과 동일하면 마지막 행을 비교하고 무시하는 삼항 표현식입니다.ld%(f=l?:-%dl)fl

실제 행은 필요하지 않으므로 --line-format공백으로 설정합니다.


MCVE에 따르면 다음과 같습니다.

  1. 삼항 검사가 필요하지 않습니다 %(f=l?:-%dl)(두 번째 숫자가 첫 번째 숫자와 같으면 두 번째 숫자를 생략합니다). 두 번째 숫자만 출력하면 됩니다.
  2. %F대부분의 경우 두 번째 숫자는 새 파일에서 변경된 첫 번째 줄 이어야 합니다 . 이전 파일에서 방금 줄을 삭제한 경우를 제외하면 새 파일의 줄 수는 0입니다. 이 경우 인쇄되는 번호는 %E새 파일에서 그룹 앞의 줄 번호입니다. 삼항은 가 됩니다 %(N=0?%dE:%dF).
  3. $1. 대신 파일 이름을 사용해야 합니다 $2.

따라서 다음과 같은 변경 사항이 적용됩니다.

#! /bin/bash
# See https://stackoverflow.com/a/255212/2072269 for details on parameters
echo "$1" # print filename
diff --changed-group-format $'%df-%(N=0?%dE:%dF)\n' --line-format='' "$2" "$5"
echo
exit 0

그러면 예상되는 출력이 제공됩니다.

$ PAGER=cat git diff --unified=0 --diff-filter=M 9e49d ad1b3
execute_cmd.c
567-567
753-753
759-758
1104-1102

patchlevel.h
28-28

subst.c
5339-5339
5345-5345
5411-5411
5433-5428
5437-5431
5445-5439
5568-5562
5572-5566
5578-5572
5583-5577
5656-5650
5660-5653
5668-5661

subst.h
276-276

관련 정보