추가 및 삭제 횟수를 추적하고 싶습니다.들어오지 못하게 하다라인이 이동되었습니다. 따라서 커밋에 추가 10개, 삭제 5개, 이동된 줄 3개가 있으면 추가 7개, 삭제 2개가 있습니다(이동된 줄은 계산하지 않음). 10과 5는 다음 코드로 제공됩니다. 3개를 생성해야 합니다(약하게 이동된 라인 감지만 필요합니다(예: 동일한 커밋에서 한 위치에서 동시에 제거되고 다른 위치에 추가되는 라인).
git 저장소에서 중요한 파일의 추가 및 삭제 횟수를 추적하기 위해 다음 명령을 사용하고 있습니다.
git log --since=2014-08-01 --date=short --pretty=format:"%ad%x09" --numstat -- file.tex
그러면 다음과 같은 결과가 생성됩니다. 여기서 첫 번째 숫자는 추가이고 두 번째 숫자는 삭제입니다.
2014-08-19
72 0 file.tex
2014-08-19
211 290 file.tex
...
세 번째 열을 추가하고 이름을 Move Row로 지정하고 싶습니다. 각 커밋에 의해 이동된 행은 각 커밋에 대한 루프에서 다음을 수행하여 찾을 수 있습니다.
- Grep은 + 또는 -로 시작하는 줄을 변경합니다.
- 스트립 선행 + 또는 -
sort
uniq -d
wc -l
이 의사 코드를 실행하는 빠르고 우아한 방법이 있습니까? 아니면 필요한 것을 얻기 위해 전체 git diff를 덤프하고 구문 분석해야 합니까?
답변1
나는 다음 구현을 작성했습니다.TxR언어. 먼저 알고리즘을 사용하여 이동 횟수를 결정합니다. 그러나 유용하지 않은 결과가 나왔다는 것을 알았습니다. 예를 들어 단순히 일부 행이 서로 중복되었기 +
때문에 행만 포함된 변경 사항에서 "행 이동"에 대해 양수 값을 식별했습니다 . +
새로운 알고리즘은 마지막 주석에서 논의됩니다.
전체 프로그램:
#!/usr/bin/env txr
@(bind option-spec
@(list (opt nil "since" :str
"Specifies the starting date (passed \
\ through to git); it is mandatory.")
(opt nil "help" :bool
"Prints this help text")))
@(bind parsed-opts @(getopts option-spec *args*))
@(if (or [parsed-opts "help"] (not [parsed-opts "since"])))
@ (output)
usage: @{self-path} --since=<date> -- git arguments
@ (end)
@ (do (opthelp option-spec)
(exit 0))
@(end)
@(do
(defun histogram (strings)
[group-reduce (hash :equal-based) identity (op succ @1) strings 0])
(defun moved (a b)
(let* ((hist-a (histogram a))
(hist-b (histogram b))
(isec [hash-isec hist-a hist-b min]))
[reduce-left + (hash-values isec) 0])))
@(next (open-command `git log --since=@[parsed-opts "since"] \
\ --date=short --pretty=format:"%H:%ad%x09" \
\ --numstat @{parsed-opts.out-args}`))
@(repeat)
@sha:@date@\t
@ (collect :gap 0)
@added@\t@removed@\t@rawpath
@ (next :string rawpath)
@ (cases)
@pro/{@before => @after}/@epi
@ (bind path `@pro/@after/@epi`)
@ (or)
@before => @after
@ (bind path after)
@ (or)
@ (bind path rawpath)
@ (end)
@ (next (open-command `git show -p @sha -- @path`))
@ (collect :vars ((+line nil) (-line nil)))
@ (cases)
+@{+line}
@ (or)
-@{-line}
@ (end)
@ (end)
@ (flatten -line +line)
@ (bind moved @(moved +line -line))
@ (end)
@ (output)
@date@\t
@ (repeat)
@added@\t@removed@\t@moved@\t@rawpath
@ (end)
@ (end)
@(end)
태그가 붙은 실행 파일에 넣었습니다. movedlines.txr
사용법 예는 다음과 같습니다.
$ ./movedlines.txr --since=2017-01-01 path/to
이 --since
옵션은 필수입니다. path/to
에 전달되는 선택적 매개변수입니다 git
. force 옵션을 지정하지 않거나 지정하는 경우 --help
프로그램은 도움말 요약을 인쇄하고 종료됩니다.
노트:
git
날짜 왼쪽에 콜론으로 구분된 SHA를 포함하도록 예제 명령의 출력 형식을 약간 변경했습니다%H
. 프로그램은 이를 구문 분석한 다음 SHA를 사용하여git show -p
각 컬렉션의 각 파일에 대해 작업을 수행할 수 있습니다. 프로그램이 이동된 열을 추가하여 시뮬레이션 출력을 역류하는 경우 SHA는 생략됩니다.git의 출력은 이름 바꾸기가 복잡한 문제임을 보여줍니다. 문법은 세 가지 경우로 나누어지며,
@(cases)
이 구문을 사용하면 명확하고 쉽게 구문 분석할 수 있습니다. 전체 경로의 이름을 바꾸면 으로 이름을 바꿉니다from => to
. 일부 구성 요소의 이름만 바꾸면be/fore/{from => to}/after
. 여러 중괄호 구문이 경로에 나타나는지 모르겠습니다. git이 이해하지 못하기 때문에 이 구문을 수정하고 일반 경로로 변환해야 합니다. 즉,be/fore/{from => to}/after
로 변환해야 합니다be/fore/to/after
. 기호 없이 경로를 이런 방식으로 출력할 수 있는 git 옵션이 있을 수도 있습니다.가 사용되므로 매개변수 목록이
open-command
필요합니다 .open-process
알고리즘은 diff
-
와+
line(선행-
OR 빼기+
)의 개별 빈도 히스토그램을 계산합니다. 그런 다음 두 히스토그램에 나타나는 히스토그램 항목만 유지하는 이러한 세트의 교집합을 계산합니다. 교차점의 조인 기능은 입니다min
. 예를 들어 라인이abc
5번 추가되고 3번 삭제되었다고 가정해 보겠습니다.(min 3 5)
예3
, 이동된 행 수입니다abc
. 이번 출퇴근. 3번 삭제abc
하고 5번 추가하면 3번 이동을 의미합니다. 이것은 결코 움직임을 감지하는 완벽한 알고리즘이 아닙니다. 선을 감지하지 못하는 등 명백한 결함이 있습니다.사실은이동하지만 들여쓰기와 같은 작은 공간 변화도 겪습니다.