Git 미드레벨 기술면접
새 면접Q. Git의 reflog는 어떤 원리로 동작하며, 실수로 삭제한 브랜치나 reset으로 잃어버린 커밋을 복구할 때 어떻게 활용할 수 있나요? reflog의 저장 위치, 보관 기간, 그리고 실제 복구 시나리오를 설명해주세요.
reflog는 .git/logs 디렉토리에 HEAD와 각 브랜치의 참조 변경 이력을 시간순으로 기록합니다. 기본적으로 90일간 보관되며, 'git reflog' 명령으로 조회할 수 있습니다. 실수로 브랜치를 삭제하거나 hard reset을 했을 때, reflog에서 이전 커밋의 SHA를 찾아 'git checkout -b [브랜치명] [SHA]' 또는 'git reset --hard [SHA]'로 복구할 수 있습니다. reflog는 로컬 저장소에만 존재하므로 원격 저장소에는 영향을 주지 않으며, 가비지 컬렉션이 실행되기 전까지 댕글링 커밋을 보호합니다.
- • reflog는 HEAD와 브랜치 참조의 모든 변경 이력을 시간순으로 기록
- • 기본 90일 보관, .git/logs에 저장되며 로컬 저장소에만 존재
- • 삭제된 브랜치나 reset으로 잃어버린 커밋을 SHA로 복구 가능
- • 가비지 컬렉션 전까지 댕글링 객체 보호
reflog가 저장되지 않는 상황이나 reflog만으로 복구할 수 없는 경우는 어떤 것들이 있으며, 이럴 때는 어떻게 대응해야 하나요?
Q. 3-way merge에서 발생하는 충돌을 해결할 때, Git이 내부적으로 사용하는 merge 전략(strategy)과 알고리즘을 설명하고, recursive, ours, octopus 전략의 차이점과 각각의 사용 사례를 설명해주세요. 또한 merge.conflictStyle 설정의 diff3 옵션이 충돌 해결에 어떻게 도움이 되는지 설명해주세요.
Git의 기본 merge 전략은 recursive로, 공통 조상(base)을 찾아 3-way merge를 수행합니다. recursive는 두 브랜치 merge 시 사용되며, 여러 공통 조상이 있을 때 임시 merge 커밋을 만들어 처리합니다. ours 전략은 충돌 시 현재 브랜치의 변경사항만 유지하며, octopus는 3개 이상의 브랜치를 동시에 merge할 때 사용됩니다. diff3 옵션은 충돌 마커에 base 버전을 추가로 표시하여, 양쪽 브랜치가 원본에서 어떻게 변경되었는지 비교할 수 있게 해줍니다. 이를 통해 각 변경의 의도를 파악하고 더 정확한 충돌 해결이 가능합니다.
- • recursive는 기본 전략으로 공통 조상 기반 3-way merge 수행
- • ours는 현재 브랜치 우선, octopus는 다중 브랜치 merge용
- • diff3는 충돌 시 base 버전을 함께 표시하여 변경 의도 파악 가능
- • 전략 선택은 브랜치 수와 충돌 해결 정책에 따라 결정
대규모 팀에서 merge 충돌을 최소화하기 위한 브랜치 전략과 코드 리뷰 프로세스를 어떻게 설계하시겠습니까?
Q. Git hooks를 활용하여 코드 품질을 자동으로 검증하는 시스템을 구축하려고 합니다. client-side hooks(pre-commit, pre-push)와 server-side hooks(pre-receive, post-receive)의 차이점을 설명하고, 각각 어떤 검증 로직을 배치하는 것이 적절한지 설명해주세요. 또한 hooks를 팀 전체에 배포하고 관리하는 전략도 제시해주세요.
client-side hooks는 개발자의 로컬 저장소에서 실행되며, pre-commit은 커밋 전 린팅과 포맷팅 검사, pre-push는 테스트 실행에 적합합니다. server-side hooks는 원격 저장소에서 실행되며, pre-receive는 푸시 거부 여부 결정(브랜치 보호, 커밋 메시지 규칙), post-receive는 CI/CD 트리거나 알림 발송에 사용됩니다. client hooks는 우회 가능하므로 중요한 검증은 server hooks에서 수행해야 합니다. hooks 배포는 package.json의 prepare 스크립트나 husky 같은 도구를 사용하여 자동 설치하거나, 별도 저장소에서 관리하고 심볼릭 링크로 연결하는 방식을 사용할 수 있습니다.
- • client hooks는 로컬 실행으로 빠른 피드백, server hooks는 강제 정책 적용
- • pre-commit은 포맷팅/린팅, pre-receive는 정책 검증에 적합
- • client hooks는 우회 가능하므로 중요 검증은 server에서 수행
- • husky나 prepare 스크립트로 팀 전체 hooks 자동 배포
hooks 실행 시간이 길어져 개발자 경험을 해치는 경우, 어떻게 최적화하거나 우회 옵션을 제공할 수 있을까요?
Q. 대규모 모노레포에서 git status와 git diff 명령이 매우 느린 문제를 해결해야 합니다. Git의 index(staging area) 구조와 파일 시스템 모니터링 방식을 설명하고, fsmonitor, split-index, feature.manyFiles 등의 최적화 기법들이 어떻게 성능을 개선하는지 설명해주세요.
Git index는 .git/index 파일에 모든 tracked 파일의 메타데이터를 저장하며, git status 실행 시 파일 시스템과 비교하여 변경사항을 탐지합니다. fsmonitor(Watchman 등)는 파일 시스템 이벤트를 모니터링하여 변경된 파일만 검사하므로 대규모 저장소에서 수십 배 빠릅니다. split-index는 index를 변경되지 않는 base와 변경사항으로 분리하여 I/O를 줄이고, feature.manyFiles 설정은 수만 개 이상의 파일이 있을 때 내부 알고리즘을 최적화합니다. 추가로 core.preloadIndex와 core.untrackedCache를 활성화하면 병렬 처리와 캐싱으로 성능이 개선됩니다.
- • index는 모든 tracked 파일 메타데이터 저장, status는 전체 파일 시스템 스캔
- • fsmonitor는 파일 시스템 이벤트 기반으로 변경 파일만 검사
- • split-index는 base와 변경사항 분리로 I/O 최적화
- • feature.manyFiles, preloadIndex, untrackedCache로 추가 최적화
모노레포 환경에서 Git 외에 Bazel이나 Nx 같은 빌드 도구를 함께 사용할 때, Git의 변경 감지와 빌드 캐시를 어떻게 통합할 수 있을까요?
Q. 여러 릴리스 브랜치에 동일한 버그 픽스를 적용해야 하는 상황에서, cherry-pick을 사용할 때 발생할 수 있는 문제점들과 해결 방법을 설명해주세요. 특히 충돌 발생 시 처리 방법, 커밋 메시지 관리, 그리고 cherry-pick 대신 고려할 수 있는 대안적인 접근 방법을 포함하여 설명해주세요.
cherry-pick은 특정 커밋을 다른 브랜치에 적용하지만, 컨텍스트가 다르면 충돌이 발생하거나 의미가 달라질 수 있습니다. 충돌 발생 시 'git cherry-pick --continue/--abort'로 해결하며, '-x' 옵션으로 원본 커밋 SHA를 메시지에 기록하여 추적성을 유지합니다. 여러 브랜치에 적용 시 스크립트로 자동화하거나 'git cherry-pick -n'으로 여러 커밋을 하나로 합칠 수 있습니다. 대안으로는 공통 fix를 별도 브랜치에서 관리하고 merge하거나, backport용 자동화 도구(예: GitHub의 backport bot)를 사용하거나, 패치 파일을 생성하여 'git am'으로 적용하는 방법이 있습니다.
- • cherry-pick은 커밋 단위 이식이지만 컨텍스트 차이로 충돌 가능
- • -x 옵션으로 원본 커밋 추적, -n으로 여러 커밋 병합 가능
- • 충돌 시 continue/abort로 처리, 스크립트로 다중 브랜치 자동화
- • 대안으로 merge 기반 관리, backport bot, patch 파일 사용
수십 개의 릴리스 브랜치를 유지보수하는 환경에서, 보안 패치를 모든 지원 버전에 자동으로 배포하는 시스템을 어떻게 설계하시겠습니까?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!