GN⁺: git absorb - 자동화된 "git commit --fixup"
(github.com/tummychow)- 페이스북이 만든
hg absorb
의 git용 포팅 버전- hg absorb는 최근 몇 년간 버전 관리 시스템에서 가장 멋진 워크플로우 개선이라고 할 수 있음
- 작업 디렉토리에 커밋되지 않은 변경 사항이 draft changeset 위에 있을 때, hg absorb를 실행하면 커밋되지 않은 수정 사항이 자동으로 적절한 draft ancestor changeset에 흡수됨
- 커밋을 생성하거나 수동으로 history 수정 규칙을 만들지 않고도 hg histedit + "roll" 작업을 수행할 수 있음
- 명령어는 수정된 라인을 보고, 해당 라인을 수정한 changeset을 찾아, 커밋되지 않은 변경 사항을 포함하도록 해당 changeset을 수정함
- 충돌 없이 변경 사항을 만들 수 없으면 커밋되지 않은 상태로 남음
- 이 워크플로우는 리뷰 피드백을 적용하는 것과 같은 작업에 매우 유용함. 파일 변경 사항을 만들고, hg absorb를 실행하면 변경 사항과 커밋 간의 매핑이 자동으로 정리됨. 마법 같은 기능임
git absorb 사용 시나리오
- 몇 개의 커밋이 있는 feature 브랜치가 있음
- 팀원이 브랜치를 리뷰하고 몇 가지 버그를 지적함
- 버그 수정 사항이 있지만, atomic 커밋을 믿기 때문에 fixes라는 불투명한 커밋에 모두 넣고 싶지 않음
- git commit --fixup을 위해 커밋 SHA를 수동으로 찾거나 수동 대화형 rebase를 실행하는 대신 다음을 수행:
- git add $FILES_YOU_FIXED
- git absorb --and-rebase
- git absorb는 어떤 커밋을 안전하게 수정할 수 있는지, 어떤 staged 변경 사항이 각 커밋에 속하는지 자동으로 식별함
- 그런 다음 이러한 변경 사항에 대한 fixup! 커밋을 작성함
- --and-rebase 플래그를 사용하면 이러한 fixup 커밋이 해당 커밋에 자동으로 통합됨
- 신뢰하지 않는 경우 출력을 수동으로 확인한 다음, git의 내장 autosquash 기능을 사용하여 fixup을 feature 브랜치에 통합할 수 있음
설치
- 최신 태그 릴리스에서 아티팩트를 다운로드하여 설치 가능
- Windows, MacOS, Linux용 아티팩트 제공
사용법
- 흡수할 변경 사항을
git add
로 추가 -
git absorb
실행 - 결과에 만족하면
git rebase -i --autosquash
실행 - 만족하지 않으면
git reset --soft
로 이전 상태로 복구
How it works (roughly)
-
git absorb
는 두 패치 P1과 P2가 교환 가능한지 확인함 - 기본적으로 마지막 10개의 커밋을 고려함
- 인덱스의 각 덩어리에 대해, 해당 덩어리가 마지막 커밋과 교환 가능한지 확인함
- 교환 불가능한 커밋을 찾으면, 해당 덩어리를 fixup 커밋으로 변환함
Configuration
Stack size
- 기본적으로 마지막 10개의 커밋을 고려함
- 더 많은 커밋을 고려하려면
.gitconfig
에maxStack
값을 설정
One fixup per fixable commit
- 기본적으로 각 흡수 가능한 덩어리에 대해 별도의 fixup 커밋을 생성함
-
-F
플래그를 사용하여 동일한 커밋에 흡수되는 모든 덩어리에 대해 하나의 fixup 커밋만 생성 가능
Auto-stage all changes if nothing staged
- 기본적으로 스테이지된 파일만 고려함
- 스테이지된 변경 사항이 없을 때 모든 변경 사항을 자동으로 스테이지하려면
autoStageIfNothingStaged
설정
Fixup target always SHA
- 기본적으로 fixup 커밋 메시지는 대상 커밋의 요약을 가리킴
- 항상 대상의 SHA를 가리키도록 설정 가능
TODO
- 강제 플래그 구현
- 원격 기본 브랜치 확인 구현
- 개별 안전 검사 비활성화를 위한 작은 강제 플래그 추가
- 모든 오류 출력이 사용자에게 유용하도록 보장
- 성공 시 더 많은 로그 출력
- 더 많은 테스트 추가
- 스택 및 교환 세부 사항 문서화
- 더 많은 교환 사례 추가
- 동시에 모든 덩어리를 메모리에 로드하지 않도록 구현
- 동시 수정으로부터 보호하기 위한 인덱스 잠금 구현
GN⁺의 정리
-
git absorb
는 Facebook의hg absorb
에서 포팅된 도구로, 커밋을 자동으로 수정하여 개발 워크플로우를 개선함 - 리뷰 피드백을 적용할 때 매우 유용하며, 수동으로 커밋을 찾거나 수정할 필요 없이 자동으로 처리해줌
- 이와 유사한 기능을 제공하는 다른 도구로는 git-autofixup이 있음. 커밋 메시지 기반으로 fixup 커밋을 자동 생성해주는 도구임
- 장점은 코드 리뷰 피드백 반영이 쉬워지고, 커밋 히스토리가 더 깔끔해진다는 점. 단점은 자동화에 너무 의존하다 보면 예상치 못한 결과가 발생할 수 있다는 점
Hacker News 의견
-
git absorb
를 사용하는 사람들은 이 도구가 매우 유용하다고 생각함- 여러 커밋이 포함된 PR이 CI에서 실패할 때,
git absorb
는 자동으로 올바른 커밋을 찾아줌 - 수동으로 커밋을 찾는 번거로움을 덜어줌
- 가짜 긍정은 거의 없고, 가짜 부정이 발생하면 수동으로 처리하면 됨
- PR이 하나의 커밋이어야 한다는 의견도 있지만, 항상 그런 것은 아님
- GitHub에서 논리적으로 작은 커밋을 선호함
- 여러 커밋이 포함된 PR이 CI에서 실패할 때,
-
git commit --fixup
을 위한 별칭을 사용하여 만족함- 현재 브랜치의 커밋을 보여주고 fzf를 통해 선택할 수 있음
- 선택한 커밋을 기반으로 fixup 커밋을 생성함
-
git absorb
를 사용해봤지만, 부모 커밋을 잘못 선택하는 경우가 많았음- 수동으로 커밋을 찾는 것이 더 나았음
- 커밋 기록을 완전히 제어하는 것을 선호함
- 이 도구는 너무 많은 마법 같음
-
git --fixup
과git rebase --autosquash
를 사용해본 적은 없지만 유용해 보임-
git-absorb
는 한 단계 더 나아가는 것 같음 - README에서 특정 상황에서 정확히 무엇을 할지 명확하지 않음
-
-
커밋과 기록을 수정하는 것에 대해 회의적임
- 실수를 수정하고 새로운 커밋을 만들고 계속 진행하는 것이 좋음
-
magit
을 사용하여 쉽게 fixup 커밋을 만들 수 있음- Emacs를 사용하지 않더라도 magit을 사용하기 위해 유지할 가치가 있음
- vscode 사용자에게는 Edamagit이 좋음
-
git commit --fixup
과git rebase --autosquash
에 대해 알게 됨- 인터랙티브 git rebase는 가장 좋아하는 Git 도구임
- 완벽한 논리적 원자 커밋을 만드는 데 도움이 됨
- 그러나 이러한 기록 편집이 때때로 역효과를 낼 수 있음
-
git rebase -i
는 다양한 요구를 충족시킴- squash, fixup, reword, delete 커밋을 인터랙티브하게 할 수 있음
- git을 사용하는 모든 사람이 배워야 함
-
초청결한 커밋 기록에 집착하는 것을 이해하지 못함
- 커밋 기록을 그렇게 자주 자세히 확인하는지 의문임
-
마지막 10개의 커밋 중 충돌 없는 수정 가능한 커밋을 선택하는 것이 이해되지 않음
- 종종 충돌을 해결하면서 fixup^를 자주 사용함
- 자동으로 타겟 커밋을 선택하는 것에 대해 신뢰하지 않음