16P by neo 21일전 | favorite | 댓글 1개
  • 페이스북이 만든 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를 실행하는 대신 다음을 수행:
    1. git add $FILES_YOU_FIXED
    2. git absorb --and-rebase
  • git absorb는 어떤 커밋을 안전하게 수정할 수 있는지, 어떤 staged 변경 사항이 각 커밋에 속하는지 자동으로 식별함
  • 그런 다음 이러한 변경 사항에 대한 fixup! 커밋을 작성함
  • --and-rebase 플래그를 사용하면 이러한 fixup 커밋이 해당 커밋에 자동으로 통합됨
  • 신뢰하지 않는 경우 출력을 수동으로 확인한 다음, git의 내장 autosquash 기능을 사용하여 fixup을 feature 브랜치에 통합할 수 있음

설치

  • 최신 태그 릴리스에서 아티팩트를 다운로드하여 설치 가능
  • Windows, MacOS, Linux용 아티팩트 제공

사용법

  1. 흡수할 변경 사항을 git add로 추가
  2. git absorb 실행
  3. 결과에 만족하면 git rebase -i --autosquash 실행
  4. 만족하지 않으면 git reset --soft로 이전 상태로 복구

How it works (roughly)

  • git absorb는 두 패치 P1과 P2가 교환 가능한지 확인함
  • 기본적으로 마지막 10개의 커밋을 고려함
  • 인덱스의 각 덩어리에 대해, 해당 덩어리가 마지막 커밋과 교환 가능한지 확인함
  • 교환 불가능한 커밋을 찾으면, 해당 덩어리를 fixup 커밋으로 변환함

Configuration

Stack size

  • 기본적으로 마지막 10개의 커밋을 고려함
  • 더 많은 커밋을 고려하려면 .gitconfigmaxStack 값을 설정

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에서 논리적으로 작은 커밋을 선호함
  • git commit --fixup을 위한 별칭을 사용하여 만족함

    • 현재 브랜치의 커밋을 보여주고 fzf를 통해 선택할 수 있음
    • 선택한 커밋을 기반으로 fixup 커밋을 생성함
  • git absorb를 사용해봤지만, 부모 커밋을 잘못 선택하는 경우가 많았음

    • 수동으로 커밋을 찾는 것이 더 나았음
    • 커밋 기록을 완전히 제어하는 것을 선호함
    • 이 도구는 너무 많은 마법 같음
  • git --fixupgit rebase --autosquash를 사용해본 적은 없지만 유용해 보임

    • git-absorb는 한 단계 더 나아가는 것 같음
    • README에서 특정 상황에서 정확히 무엇을 할지 명확하지 않음
  • 커밋과 기록을 수정하는 것에 대해 회의적임

    • 실수를 수정하고 새로운 커밋을 만들고 계속 진행하는 것이 좋음
  • magit을 사용하여 쉽게 fixup 커밋을 만들 수 있음

    • Emacs를 사용하지 않더라도 magit을 사용하기 위해 유지할 가치가 있음
    • vscode 사용자에게는 Edamagit이 좋음
  • git commit --fixupgit rebase --autosquash에 대해 알게 됨

    • 인터랙티브 git rebase는 가장 좋아하는 Git 도구임
    • 완벽한 논리적 원자 커밋을 만드는 데 도움이 됨
    • 그러나 이러한 기록 편집이 때때로 역효과를 낼 수 있음
  • git rebase -i는 다양한 요구를 충족시킴

    • squash, fixup, reword, delete 커밋을 인터랙티브하게 할 수 있음
    • git을 사용하는 모든 사람이 배워야 함
  • 초청결한 커밋 기록에 집착하는 것을 이해하지 못함

    • 커밋 기록을 그렇게 자주 자세히 확인하는지 의문임
  • 마지막 10개의 커밋 중 충돌 없는 수정 가능한 커밋을 선택하는 것이 이해되지 않음

    • 종종 충돌을 해결하면서 fixup^를 자주 사용함
    • 자동으로 타겟 커밋을 선택하는 것에 대해 신뢰하지 않음