깃의 고급 기능

refs

깃에서 커밋은 코드 이력 관리의 기준이며, 여러 기능에서 해시 값을 참조한다.

깃에서 참조하는 해시값을 refs 목록으로 가지고 있다.

  • 해시
    • 생성된 모든 해시 값 확인

      $ git show 해시값
      
  • 역조회
    • 포인터의 해시 값 구하기

      $ git rev-parse 브랜치이름
      
  • 참조 목록
    • 생성된 해시 값을 쉽게 참조할 수 있도록 refs 목록을 생성

        $ ls .git/refs -all // 모든 refs 목록 조회
            
        [dk@Chiptune gitstudy12 % ls .git/refs -all
        ls: -all: No such file or directory
        .git/refs:
        heads	tags
      
    • 브랜치, 태그, 헤드 등에서 생성 및 참조한 커밋 해시값을 확인할 수 있다

reflog

참조 기록은 아래의 명령을 사용하여 조회할 수 있다.

$ git reflog
  • reflog는 시스템에서 정의한 며칠 간 만의 기록만 보관한다.
  • reflog의 기록들은 HEAD@{숫자} 형태이다.
$ git show HEAD@{0} // 커밋 정보 확인, 0번째 헤드 포인터 조회
$ git show master@{yesterday} // 마스터 브랜치의 어제 작업 내역 조회

파일 애너테이션

  • blame
    • 커밋의 메타 정보를 코드 라인별로 같이 결합하여 출력한다.
    • 코드를 수정한 사람과 시점 등을 쉽게 판별할 수 있어 수많은 커밋에서 문제를 찾기 쉽게 한다
  • 명령어

      $ git blame 파일명
        
      dk@Chiptune gitstudy12 % git blame index.html 
      ^23609f1 (Chiptune93 2023-07-15 01:02:49 +0900 1) hello world
    
  • 옵션 활용

      $ git blame -L 시작줄,마지막줄 파일이름
        
      dk@Chiptune gitstudy12 % git blame -L 1,3 index.html 
      ^23609f1 (Chiptune93 2023-07-15 01:02:49 +0900 1) hello world
      a51448b5 (Chiptune93 2023-07-15 01:13:04 +0900 2) 123
      a51448b5 (Chiptune93 2023-07-15 01:13:04 +0900 3) 234
    
    • -L : 특정 파일 라인을 지정하여 조회
    • -e : 사용자 이름 대신 이메일을 출력
    • -w : 공백문자 무시
    • -M : 같은 파일 내에서 복사나 이동을 감지
    • -C : 다른 파일에서 이동이나 복사된 것을 감지

replace

기존 커밋을 다른 커밋인 것 처럼 변경하는 기능.

커밋이 많은 오래된 저장소를 분리할 수 있다.

  • 저장소 분리
    • 특정 커밋을 기준으로 브랜치를 나눈다.

      $ git branch worked {commitHash}
      
    • 원격 저장소를 새로 등록한다. 이름은 old 로, 이전 오래된 커밋 저장 용도의 저장소이다.

      $ git remote add old {URL}
      
    • 나눈 브랜치를 원격에 push 한다.

      $ git push old worked:master
      

    Untitled

    • 분리를 위해서는 가상의 임시 객체를 하나 생성해야 한다. 여기서는 커밋3을 기준으로 원격에 푸시 하였고, 분리 기준은 커밋2 이다.

      $ echo "devide history" | git commit-tree w2^{tree}
      

    Untitled

    • 생성된 임시 객체를 다른 커밋 객체와 리베이스하여 병합한다.

      $ git rebase --onto new w2 // 새로운 임시 객체 -> w2 리베이스
      

    Untitled

    • 이제 새로운 원격 저장소를 생성하여 등록한다. 여기에는 새 히스토리가 쌓일 저장소이다.

      $ git remote add origin {URL}
      
    • 분리 작업한 로컬 저장소를 origin 원격 저장소로 푸시한다.

      $ git push -u origin master
      
  • 저장소 연결
    • 로컬 저장소를 분리하여 각각의 원격 저장소를 생성한 상태에서, 하나로 합치는 작업을 수행한다.
    • 분리된 두 원격 저장소 중, 마지막에 작업한 커밋으로 원격 저장소를 복사한다.

      $ git clone {origin-url} folder1
      
    • 복제된 저장소는 분리된 커밋만 가지고 있으므로, 이전 커밋 정보들이 보관된 원격 저장소를 등록한다.

      $ git remote add worked {old-url}
      
    • 원격 저장소를 페치하여 커밋들은 가져온다. 페치로 가져오는 이유는 수동으로 커밋을 변경하여 병합하기 때문이다.

      $ git fetch worked // 커밋 내려받기
      
    • 이제 origin/master 와 worked/master 를 replace 명령어로 연결한다.

      $ git replace {origin/master HEAD} {worked/master HEAD}
      

    Untitled

가비지 콜렉트

  • 가비지
    • 연결 고리가 없는 고립된 객체들이 생성된다.
    • 리셋, 리베이스 등을 자주 할 때 발생한다.

    깃의 커밋은 생성된 객체의 연결 고리를 설정하는 동작이다. 커밋을 변경하면 새로운 객체로 연결 고리를 재설정 하는데 기존에 연결된 객체는 삭제되지 않고 유지된다. 이러한 과정에서 불필요한 가비지가 생성되는데, 남기는 이유는 나중에 수동으로 커밋 복구 시, 사용 되기 때문이다.

  • 압축 관리
    • 깃의 내부 원리는 SHA1 해시와 객체의 응용.
    • 대부분의 작업은 객체를 생성하고 연결하는 동작.
    • 이러한 객체가 많아지면 용량이 계속 커지므로, 연결 고리가 없는 객체는 pack 파일 형태로 압축하여 저장한다.
  • 실행
    • 깃은 가비지를 정리하기 위한 별도의 gc 명령어를 제공한다.
    • 자동으로 실행되나, 수동으로도 가능하다

      $ git gc --auto // gc가 실행되면 객체를 압축하고 pack 형태로 저장하게 된다.
      
  • refs 압축
    • gc 명령어는 객체와 더불어 refs 도 압축을 지원한다.
    • 압축 전 파일은 삭제되고, .git/packed-refs 파일을 생성한다.
    • 새로운 파일은 다시 refs 에 생성되고, 검색 시에도 refs 를 찾은 후 packed-refs 를 찾는다.
  • 환경 설정
    • gc.reflogExpire : reflog가 보존되는 기간을 설정. 기본은 90일
    • gc.reflogExpireUnreachable : 기본값은 30일.
    • gc.aggressiveWindow : 창의 크기를 정한다. 기본 값은 250이다.
    • gc.aggressiveDepth : 압축에 사용되는 매개변수, 기본 50.
    • gc.pruneExpire : 저장소에 쓰는 다른 프로세스와 동시 실행될 때 손상을 방지한다.
    • gc.worktreePruneExpire : 유예 기간을 설정할 수 있다.

prune

고립된 객체를 정리하는 내부 유틸리티.

  • 고립된 객체
    • 객체 간 연결 고리가 끊겨 명령어를 사용해도 해당 객체에 접근할 수 없는 객체를 의미한다.
  • 객체 삭제
    • 커밋을 하드리셋 하더라도, 내부적으로 생성한 객체를 물리적으로 삭제하지 않는다.
    • 제거한 커밋을 체크아웃이 가능하다.
    • 리셋은 단지 객체 연결 고리를 해제하여 끊긴 상태로 처리하며, 이 커밋은 깃 내부 저장소에 고립된 객체로 남는다.
  • 객체 정리
    • prune
      • --dry-run : 실행하지 않고 작업할 내용만 출력
      • --verbose : 작업한 결과를 출력
      $ git prune --dry-run --verbose
      
    • 고립한다는 것은 어떤 명령어로도 해당 객체에 접근할 수 없어야 한다.
    • 깃은 객체의 연결 고리를 reflog에 이중으로 기록한다.
    • 따라서, reflog에 기록된 연결 고리 링크도 같이 삭제해주어야 한다.

      $ git reflog expire --expire=now --expire-unreachable=now --all // reflog 삭제
      
    • 실제로 삭제 작업을 하려면 --expire 옵션을 사용한다.

      $ git prune --expire now -v
      
  • 원격 작업
    • 원격 저장소에서도 고립된 객체가 존재할 수 있으며, prune 작업을 수행할 수 있다.

      $ git remote prune
      $ git fetch --prune
      

rerere

  • 동일한 충돌 발생
    • reuse recorded resolution
    • 어떤 문제로 충돌이 발생할 때 이를 기록하는 기능이다.
    • 미리 기록한 해결을 바탕으로 추후 비슷한 문제 발생 시, 자동으로 해결한다.
  • 활성화
    • 기본적으로 활성화 되어 있지 않다. 활성화를 위해서는 아래 명령을 실행한다.

      $ git config rerere.enabled true
      
  • 상태 확인
    • 아래 명령어로 충돌 발생 시, 상태를 확인할 수 있다.

      $ git rerere status
      

© 2024. Chiptune93 All rights reserved.