Git 면접 질문 및 답변

GitBeginner
지금 연습하기

소개

Git 면접 질문 및 답변에 대한 종합 가이드에 오신 것을 환영합니다! 신진 개발자, 숙련된 엔지니어 또는 DevOps 전문가이든 관계없이 효과적인 버전 관리 및 협업 개발을 위해서는 Git 숙달이 필수적입니다. 이 문서는 기본 개념 및 고급 워크플로우부터 실용적인 문제 해결 및 모범 사례에 이르기까지 기술 면접에서 탁월한 성과를 거두는 데 필요한 지식과 자신감을 갖추도록 세심하게 설계되었습니다. Git 에 대한 이해를 공고히 하고, Git 의 복잡성을 탐구하며, 다양한 시나리오 및 애플리케이션에 걸친 전문성을 바탕으로 면접관에게 깊은 인상을 줄 준비를 하십시오.

GIT

Git 기본 개념

Git 이란 무엇이며 SVN 과 같은 중앙 집중식 버전 관리 시스템과 어떻게 다른가요?

답변:

Git 은 분산 버전 관리 시스템 (DVCS) 으로, 모든 개발자가 저장소 기록의 전체 복사본을 가지고 있습니다. 단일 서버가 권한 있는 복사본을 보유하는 중앙 집중식 시스템 (예: SVN) 과 달리, Git 은 분산 특성 덕분에 오프라인 작업, 더 빠른 작업 및 더 강력한 브랜칭/병합 기능을 제공합니다.


Git 에서 파일의 세 가지 주요 상태를 설명하세요.

답변:

세 가지 주요 상태는 다음과 같습니다. 수정됨 (파일이 변경되었지만 아직 스테이징되지 않음), 스테이징됨 (다음 스냅샷에 커밋하도록 표시된 파일), 커밋됨 (파일 데이터가 로컬 데이터베이스에 안전하게 저장됨). 이는 각각 작업 디렉토리, 스테이징 영역 (인덱스), Git 디렉토리에 해당합니다.


Git 의 '스테이징 영역'(또는 '인덱스') 의 목적은 무엇인가요?

답변:

스테이징 영역은 다음 커밋을 준비하는 중간 영역입니다. 이를 통해 작업 디렉토리의 변경 사항 중 어떤 것을 다음 커밋에 포함할지 선택적으로 선택할 수 있으며, 한 번에 모든 수정된 파일을 커밋하는 대신 사용할 수 있습니다. 이는 커밋에 대한 세밀한 제어를 가능하게 합니다.


Git 은 데이터를 어떻게 저장하나요? '커밋 객체'란 무엇인가요?

답변:

Git 은 파일 변경 목록이 아닌 스냅샷 시리즈로 데이터를 저장합니다. 커밋 객체는 특정 시점의 전체 저장소 스냅샷입니다. 각 커밋은 프로젝트 파일, 메타데이터 (작성자, 커미터, 타임스탬프) 를 나타내는 트리 객체에 대한 포인터와 해당 부모 커밋에 대한 포인터를 포함합니다.


Git 에서 '브랜치'란 무엇이며 왜 유용한가요?

답변:

Git 의 브랜치는 단순히 커밋을 가리키는 가볍고 이동 가능한 포인터입니다. 브랜치는 개발자가 안정적인 코드베이스에 영향을 주지 않고 새로운 기능이나 버그 수정을 위해 메인 개발 라인에서 벗어날 수 있도록 해주기 때문에 유용합니다. 이는 병렬 개발 및 실험을 가능하게 합니다.


'git fetch'와 'git pull'의 차이점을 설명하세요.

답변:

'git fetch'는 원격 저장소에서 새 데이터를 다운로드하지만 로컬 작업 파일에는 통합하지 않습니다. 원격 추적 브랜치만 업데이트합니다. 'git pull'은 본질적으로 'git fetch' 다음에 'git merge'(또는 'git rebase') 를 수행하는 것으로, 변경 사항을 다운로드한 다음 현재 로컬 브랜치에 자동으로 통합합니다.


'병합 충돌'이란 무엇이며 어떻게 해결하나요?

답변:

병합 충돌은 두 개의 다른 브랜치에서 변경한 내용이 동일한 파일의 동일한 줄을 수정했거나, 한 브랜치에서 삭제한 파일을 다른 브랜치에서 수정했기 때문에 Git 이 변경 사항을 자동으로 병합할 수 없을 때 발생합니다. 이를 해결하려면 충돌이 발생한 파일을 수동으로 편집하고 원하는 변경 사항을 선택한 다음, 해결된 파일을 'git add'하고 'git commit'합니다.


'git rebase'란 무엇이며 'git merge' 대신 언제 사용해야 하나요?

답변:

'git rebase'는 일련의 커밋을 한 브랜치에서 다른 브랜치로 다시 적용하여 커밋 기록을 효과적으로 다시 작성하는 명령입니다. 선형 프로젝트 기록을 유지하거나, 병합 커밋을 피하거나, 푸시하기 전에 로컬 커밋을 정리하기 위해 사용할 수 있습니다. 일반적으로 메인으로 병합하기 전에 로컬 기능 브랜치에 선호됩니다.


Git 에서 변경 사항을 되돌리는 방법은 무엇인가요? 몇 가지 명령어를 언급하세요.

답변:

변경 사항을 되돌리는 방법에는 여러 가지가 있습니다. 'git reset'은 파일을 스테이징 해제하거나 HEAD 포인터를 이전 커밋으로 이동할 수 있습니다. 'git revert'는 이전 커밋의 변경 사항을 되돌리는 새 커밋을 생성하여 기록을 보존합니다. 'git checkout -- '은 특정 파일에 대한 작업 디렉토리의 변경 사항을 삭제합니다.


'.gitignore' 파일의 목적은 무엇인가요?

답변:

'.gitignore' 파일은 Git 이 무시해야 하는 의도적으로 추적되지 않은 파일을 지정합니다. 이는 임시 파일, 빌드 아티팩트, IDE 구성 파일 또는 민감한 데이터가 저장소에 실수로 커밋되는 것을 방지하는 데 유용합니다. 파일의 각 줄은 무시할 파일 또는 디렉토리에 대한 패턴을 지정합니다.


고급 Git 명령 및 워크플로우

git rebasegit merge의 차이점을 설명하세요.

답변:

git merge는 새로운 병합 커밋을 생성하여 브랜치를 결합하며 기록을 보존합니다. git rebase는 커밋 시퀀스를 새 기본 커밋으로 이동하거나 결합하여 기록을 효과적으로 다시 작성하여 선형 커밋 기록을 생성합니다. Rebase 는 병합 전에 로컬 브랜치를 정리하는 데 자주 사용됩니다.


git cherry-pick은 언제 사용하나요?

답변:

git cherry-pick은 한 브랜치의 특정 커밋을 다른 브랜치에 적용하는 데 사용됩니다. 이는 핫픽스, 전체 브랜치를 병합하지 않고 단일 기능 커밋을 적용하거나 실수로 잘못된 브랜치에 만든 커밋을 이동해야 할 때 유용합니다.


git reflog의 목적을 설명하세요.

답변:

git reflog는 커밋, 병합, 리베이스, 리셋을 포함하여 저장소 HEAD 의 모든 변경 사항을 기록합니다. 이는 브랜치나 태그로 더 이상 접근할 수 없는 경우에도 손실된 커밋을 복구하거나 이전 상태로 되돌릴 수 있게 해주는 강력한 안전망입니다.


이미 원격 저장소로 푸시된 커밋을 되돌리려면 어떻게 해야 하나요?

답변:

푸시된 커밋을 되돌리려면 git revert <commit-hash>를 사용합니다. 이는 지정된 커밋의 변경 사항을 취소하는 새 커밋을 생성하여 기록을 보존합니다. 공유 브랜치에서 git reset --hard보다 안전한 이유는 기록을 다시 작성하지 않기 때문입니다.


git stash란 무엇이며 언제 사용하나요?

답변:

git stash는 커밋할 준비가 되지 않은 변경 사항을 임시로 저장하여 브랜치를 전환하거나 다른 작업을 수행할 수 있게 합니다. 수정된 추적 파일과 스테이징된 변경 사항을 저장하며, 나중에 git stash pop 또는 git stash apply를 사용하여 다시 적용할 수 있습니다.


'스쿼시 커밋'의 개념과 이를 수행하는 방법을 설명하세요.

답변:

스쿼시 커밋은 여러 커밋을 단일 새 커밋으로 결합합니다. 이는 병합 전에 기능 브랜치의 기록을 정리하여 프로젝트 기록을 더 간결하게 만드는 데 유용합니다. git rebase -i <commit-hash-before-first-commit-to-squash>를 사용하고 커밋을 'squash' 또는 'fixup'으로 표시하여 수행할 수 있습니다.


git reset --soft, --mixed, --hard의 차이점은 무엇인가요?

답변:

--soft는 HEAD 를 이동하지만 변경 사항은 스테이징된 상태로 유지합니다. --mixed(기본값) 는 HEAD 를 이동하고 변경 사항의 스테이징을 해제합니다. --hard는 HEAD 를 이동하고 작업 디렉토리 및 스테이징 영역의 모든 변경 사항을 삭제합니다. 각 옵션은 커밋 기록과 작업 디렉토리 상태에 다르게 영향을 미칩니다.


리베이스 작업 중 병합 충돌을 어떻게 해결하나요?

답변:

리베이스 중 Git 은 충돌이 있는 각 커밋에서 일시 중지됩니다. 파일에서 충돌을 수동으로 해결하고, 해결된 파일을 git add한 다음, git rebase --continue로 리베이스를 계속합니다. 중단하려면 git rebase --abort를 사용합니다.


익숙한 일반적인 Git 워크플로우 (예: Git Flow, GitHub Flow) 를 설명하세요.

답변:

GitHub Flow 는 가벼운 브랜치 기반 워크플로우입니다. 개발자는 main에서 기능 브랜치를 생성하고, 변경 사항을 만들고, 검토를 위해 풀 리퀘스트를 열고, 승인되면 main으로 병합합니다. main은 항상 배포 가능합니다. 이는 지속적인 배포를 촉진하고 브랜칭을 단순화합니다.


git bisect는 언제 사용하나요?

답변:

git bisect는 커밋 기록을 통해 이진 검색을 수행하여 버그를 도입한 커밋을 찾는 데 사용됩니다. 커밋을 '좋음' 또는 '나쁨'으로 표시하면 Git 이 범인 커밋이 식별될 때까지 범위를 좁혀 디버깅 속도를 크게 높입니다.


시나리오 기반 문제 해결

로컬 feature 브랜치에 여러 커밋을 했지만, 마지막 두 커밋에 푸시해서는 안 되는 민감한 정보가 포함되어 있다는 것을 깨달았습니다. 푸시하기 전에 어떻게 제거하나요?

답변:

git reset --soft HEAD~2를 사용하여 마지막 두 커밋의 커밋을 해제하면서 변경 사항을 스테이징 상태로 유지합니다. 그런 다음 민감한 정보를 제거하고 새 커밋을 생성합니다. 또는 git rebase -i HEAD~3을 사용하여 커밋을 '스쿼시'하거나 '편집'하여 내용을 제거할 수 있습니다.


기능 브랜치에서 작업 중이며 중요한 버그를 수정하기 위해 main으로 일시적으로 전환해야 합니다. 기능 브랜치에 커밋되지 않은 변경 사항이 있습니다. 이를 수행하는 가장 안전한 방법은 무엇인가요?

답변:

git stash를 사용하여 커밋되지 않은 변경 사항을 저장합니다. 이렇게 하면 작업 디렉토리가 정리되어 브랜치를 전환할 수 있습니다. main에서 버그를 수정한 후 기능 브랜치로 다시 전환하고 git stash pop을 사용하여 변경 사항을 다시 적용합니다.


저장소에 대용량 바이너리 파일 (예: .zip 파일) 을 실수로 커밋했으며 이미 원격으로 푸시되었습니다. 저장소 기록에서 어떻게 제거하나요?

답변:

이것은 기록을 다시 작성해야 합니다. 가장 안전한 방법은 git filter-repo( git filter-branch보다 권장됨) 를 사용하여 모든 커밋에서 파일을 제거하는 것입니다. 실행 후에는 기록 다시 작성을 협업자에게 알리고 git push --force-with-lease로 원격을 업데이트합니다.


로컬 main 브랜치로 origin/main의 변경 사항을 풀 (pull) 했지만, 이제 로컬 main에 병합 충돌이 발생했습니다. 너무 일찍 풀했다는 것을 깨닫고 풀하기 전 상태로 되돌리고 싶습니다. 어떻게 해야 하나요?

답변:

풀이 병합 커밋을 생성했다면 git reset --hard HEAD~1을 사용하여 병합 전 커밋으로 되돌립니다. 패스트포워드였다면 git reflog를 사용하여 풀하기 전 커밋 해시를 찾은 다음 git reset --hard <commit_hash>를 사용합니다.


동료가 main에 버그를 유발하는 커밋을 푸시했습니다. 후속 커밋에 영향을 주지 않고 해당 특정 커밋만 되돌려야 합니다. 어떻게 해야 하나요?

답변:

git revert <commit_hash>를 사용합니다. 이는 지정된 커밋에서 도입된 변경 사항을 취소하는 새 커밋을 생성합니다. 기록을 다시 작성하지 않으므로 공유 기록에 안전합니다.


로컬 feature 브랜치를 푸시하려고 하지만, 원격에 새 커밋이 있기 때문에 Git 이 푸시를 거부합니다. 해당 변경 사항을 통합한 다음 작업을 푸시하고 싶으며, 커밋은 위에 유지합니다.

답변:

git pull --rebase를 사용합니다. 이는 원격 변경 사항을 가져온 다음 업데이트된 원격 브랜치 위에 로컬 커밋을 다시 적용합니다. 이렇게 하면 병합 커밋이 생성되지 않고 선형 기록이 유지됩니다.


로컬 feature 브랜치에 커밋을 했지만, 해당 커밋이 다른 새 브랜치에 속해야 한다는 것을 깨달았습니다. 해당 커밋을 새 브랜치로 이동하고 현재 브랜치를 재설정하려면 어떻게 해야 하나요?

답변:

먼저 새 브랜치를 생성하고 전환합니다: git branch new-feature-branchgit checkout new-feature-branch. 그런 다음 해당 커밋 이전의 상태로 원래 feature 브랜치를 재설정합니다: git checkout feature 다음에 git reset --hard HEAD~N (여기서 N 은 이동할 커밋 수).


동료의 브랜치 (their-feature) 에서 단일 커밋을 현재 my-feature 브랜치로 체리픽 (cherry-pick) 해야 합니다. 어떻게 해야 하나요?

답변:

먼저 my-feature 브랜치에 있는지 확인합니다. 그런 다음 git cherry-pick <commit_hash_from_their_feature>를 사용합니다. 해당 브랜치가 로컬에 없다면 먼저 가져와야 할 수 있습니다: git fetch origin their-feature.


커밋을 했지만 파일을 추가하는 것을 잊었습니다. 새 커밋을 만들지 않고 해당 파일을 이전 커밋에 포함시키고 싶습니다.

답변:

잊어버린 파일을 스테이징 영역에 추가합니다: git add <forgotten_file>. 그런 다음 이전 커밋을 수정합니다: git commit --amend --no-edit. 이렇게 하면 메시지를 변경하지 않고 새 파일로 마지막 커밋이 업데이트됩니다.


main 브랜치가 origin/main보다 몇 개의 커밋 앞서 있으며, 이 커밋들은 푸시되지 말았어야 합니다. 로컬 mainorigin/main과 정확히 일치하도록 강제하고 싶습니다.

답변:

먼저 로컬 main이 체크아웃되었는지 확인합니다. 그런 다음 git reset --hard origin/main을 사용합니다. 이렇게 하면 origin/main에 없는 main의 모든 로컬 커밋이 삭제되고 작업 디렉토리가 원격과 일치하도록 재설정됩니다.


역할별 Git 활용

DevOps 엔지니어로서 인프라스트럭처 코드 (IaC) 구성을 관리하고 환경 간 일관성을 보장하기 위해 Git 을 어떻게 사용하겠습니까?

답변:

IaC 구성 (예: Terraform, Ansible) 을 Git 저장소에 저장하고, 각 환경 (dev, staging, prod) 에 대해 브랜치를 사용합니다. Git 태그는 안정적인 릴리스를 표시하는 데 사용되며, 풀 리퀘스트는 변경 사항을 병합하기 전에 동료 검토 및 자동화된 테스트를 강제하여 일관성과 추적성을 보장합니다.


프론트엔드 개발자로서 기능 브랜치를 관리하고, UI 컴포넌트 라이브러리를 처리하며, 디자인 시스템과 통합하기 위해 Git 을 어떻게 사용하겠습니까?

답변:

새로운 UI 컴포넌트 또는 페이지에 대해 기능 브랜치를 생성합니다. 컴포넌트 라이브러리의 경우 Git 서브모듈 또는 별도의 저장소를 사용하고 버전 업데이트를 통해 이를 업데이트합니다. 디자인 시스템과의 통합은 전용 디자인 시스템 저장소 또는 패키지에서 변경 사항을 풀 (pull) 하여 일관된 스타일링과 컴포넌트를 보장하는 것을 포함합니다.


백엔드 개발자로서 팀 환경에서 Git 을 사용하여 데이터베이스 스키마 마이그레이션을 어떻게 관리하나요?

답변:

데이터베이스 스키마 마이그레이션 스크립트는 애플리케이션 코드와 함께 Git 에서 버전 관리됩니다. 각 마이그레이션은 별도의 파일이며, 변경 사항은 풀 리퀘스트를 통해 검토됩니다. Flyway 또는 Liquibase 와 같은 도구를 사용하여 마이그레이션을 적용하며, 이들의 상태도 추적되어 모든 팀원이 올바른 순서로 마이그레이션을 적용하도록 보장합니다.


릴리스 관리자라면 버전 관리, 핫픽스, 여러 릴리스 라인 관리를 위해 Git 을 어떻게 활용하겠습니까?

답변:

Git 태그를 사용하여 공식 릴리스 (예: v1.0.0) 를 표시합니다. 핫픽스는 전용 hotfix 브랜치에 적용하거나 릴리스 브랜치에 직접 적용한 다음 main/develop으로 체리픽 (cherry-pick) 합니다. 여러 릴리스 라인은 각 주요 버전에 대해 별도의 장기 유지 브랜치를 유지하여 관리됩니다.


QA 엔지니어로서 테스트 케이스를 추적하고, 테스트 데이터를 관리하며, 버그를 효과적으로 보고하기 위해 Git 을 어떻게 사용하겠습니까?

답변:

테스트 케이스와 자동화 스크립트는 Git 에서 버전 관리됩니다. 테스트 데이터는 별도의 Git 추적 파일에서 관리하거나 동적으로 생성할 수 있습니다. 버그 보고서는 문제가 발견된 특정 Git 커밋 또는 브랜치를 참조하여 개발자가 재현 및 디버깅하는 데 도움을 줍니다.


데이터 과학자로서 노트북, 데이터셋 (또는 해당 참조), 모델 버전을 관리하기 위해 Git 을 어떻게 사용하겠습니까?

답변:

Jupyter 노트북과 Python 스크립트를 Git 에서 버전 관리합니다. 대규모 데이터셋은 일반적으로 직접 저장되지 않고 Git LFS 또는 외부 스토리지를 통해 참조됩니다. 모델 버전은 모델 아티팩트 (또는 해당 해시) 와 이를 생성한 코드를 저장하여 추적하며, 특정 Git 커밋에 연결합니다.


기술 작가로서 문서를 관리하고, 개발자와 협업하며, 다양한 제품 릴리스에 대한 버전을 처리하기 위해 Git 을 어떻게 사용하겠습니까?

답변:

문서는 Git 저장소 내의 Markdown 또는 AsciiDoc 으로 저장합니다. 풀 리퀘스트를 사용하여 검토 및 개발자 기여를 협업합니다. 다양한 제품 릴리스에 대한 버전 관리는 코드와 함께 문서를 브랜칭하거나, Git 태그를 사용하여 제품 릴리스에 해당하는 문서 버전을 표시함으로써 처리됩니다.


보안 엔지니어가 Git 을 사용하여 보안 정책, 구성 기준선 및 변경 사항 감사 를 관리하는 방법을 설명하세요.

답변:

보안 정책 및 구성 기준선 (예: 방화벽, OS 강화) 은 Git 에서 버전 관리됩니다. 모든 변경 사항은 풀 리퀘스트를 통해 이루어지며, 동료 검토 및 승인이 필요합니다. Git 의 커밋 기록은 누가 무엇을 언제 왜 변경했는지에 대한 불변의 감사 추적을 제공하며, 이는 규정 준수 및 사고 대응에 중요합니다.


실용적이고 실제적인 도전 과제

feature 브랜치에 여러 커밋을 했지만, 마지막 두 커밋이 다른 브랜치에 있었어야 한다는 것을 깨달았습니다. 어떻게 이동시키겠습니까?

답변:

feature 브랜치에서 git reset --hard HEAD~2를 사용하여 마지막 두 커밋을 제거합니다. 그런 다음 재설정 전 원래 상태에서 새 브랜치를 생성합니다 (예: git branch new-feature <original_commit_hash>). 그런 다음 해당 브랜치로 두 커밋을 체리픽 (cherry-pick) 합니다.


실수로 민감한 정보 (예: API 키) 를 커밋하고 원격 저장소로 푸시했습니다. Git 기록에서 어떻게 제거하나요?

답변:

git filter-repo(권장) 또는 git filter-branch를 사용하여 기록을 다시 작성하고 파일을 제거합니다. 다시 작성한 후에는 git push --force로 원격을 업데이트합니다. 협업자에게 다시 클론하거나 작업을 리베이스 (rebase) 하도록 알립니다.


git merge 대신 git rebase를 사용하는 시나리오를 설명하세요.

답변:

git rebase는 특히 기능 브랜치를 main으로 병합하기 전에 깔끔하고 선형적인 기록을 원할 때 선호됩니다. 대상 브랜치 위에 커밋을 다시 적용하여 병합 커밋을 피하고 기록을 더 쉽게 추적할 수 있도록 합니다.


기능 작업을 하고 있지만 긴급한 버그 수정이 발생했습니다. 커밋되지 않은 변경 사항이 있습니다. 현재 작업을 잃지 않고 버그를 수정하기 위해 main 브랜치로 전환하려면 어떻게 해야 하나요?

답변:

git stash를 사용하여 커밋되지 않은 변경 사항을 임시로 저장합니다. 그런 다음 main으로 전환하여 버그를 수정하고 커밋합니다. 기능 브랜치로 다시 전환한 후 git stash pop을 사용하여 변경 사항을 다시 적용합니다.


이미 푸시된 특정 커밋을 후속 커밋에 영향을 주지 않고 되돌리려면 어떻게 해야 하나요?

답변:

git revert <commit_hash>를 사용합니다. 이는 지정된 커밋에서 도입된 변경 사항을 취소하는 새 커밋을 생성하여 프로젝트 기록을 보존하고 기록을 다시 작성하지 않습니다.


커밋을 했지만 파일을 추가하는 것을 잊었습니다. 이전 커밋에 파일을 추가하려면 어떻게 해야 하나요?

답변:

잊어버린 파일을 스테이징 영역에 추가합니다 (git add <file>). 그런 다음 git commit --amend --no-edit를 사용하여 메시지를 변경하지 않고 스테이징된 파일을 이전 커밋에 추가합니다.


로컬 main 브랜치가 원격 main보다 뒤처져 있습니다. 병합 커밋을 생성하지 않고 로컬 브랜치를 업데이트하려면 어떻게 해야 하나요?

답변:

git pull --rebase를 사용합니다. 이는 원격에서 변경 사항을 가져온 다음 업데이트된 원격 브랜치 위에 로컬 커밋을 다시 적용하여 선형적인 기록을 만듭니다.


현재 브랜치에 병합하지 않고 동료의 브랜치에서 변경 사항을 검토해야 합니다. 어떻게 해야 하나요?

답변:

git fetch origin <colleague_branch_name>:<local_tracking_branch_name>을 사용하여 병합하지 않고 해당 브랜치를 가져옵니다. 그런 다음 git diff <local_tracking_branch_name> 또는 git log <local_tracking_branch_name>을 사용하여 변경 사항을 검토할 수 있습니다.


git reset --soft, git reset --mixed, git reset --hard의 차이점을 설명하세요.

답변:

--soft는 HEAD 를 이동하지만 변경 사항을 스테이징 상태로 유지합니다. --mixed(기본값) 는 HEAD 를 이동하고 변경 사항을 스테이징 해제합니다. --hard는 HEAD 를 이동하고 작업 디렉토리 및 스테이징 영역의 모든 변경 사항을 삭제하므로 파괴적입니다.


파일의 특정 코드 줄 작성자를 어떻게 찾을 수 있나요?

답변:

git blame <file_path>를 사용합니다. 이 명령은 지정된 파일의 각 줄에 대한 커밋과 작성자를 보여주므로 특정 코드 세그먼트의 기록을 추적하는 데 도움이 됩니다.


Git 문제 해결

병합 충돌을 어떻게 해결하나요?

답변:

병합 충돌은 Git 이 두 브랜치 간의 변경 사항을 자동으로 조정할 수 없을 때 발생합니다. 충돌이 발생한 파일을 식별하고, 원하는 변경 사항을 선택하기 위해 수동으로 편집하며, 충돌 마커 (<<<<<<<, =======, >>>>>>>) 를 제거한 다음, 해결된 파일을 git add하고 git commit을 실행합니다.


비정상적인 전달 (non-fast-forward) 오류로 인해 git push가 실패하는 경우 어떤 단계를 거치겠습니까?

답변:

비정상적인 전달 오류는 로컬 브랜치에 없는 변경 사항이 원격 브랜치에 있다는 것을 의미합니다. 먼저 git pull을 사용하여 원격 변경 사항을 로컬 브랜치로 가져와 병합합니다. 잠재적인 병합 충돌을 해결한 후 git push를 다시 시도합니다.


실수로 민감한 정보를 커밋했습니다. Git 기록에서 어떻게 제거하나요?

답변:

기록에서 민감한 정보를 제거하기 위해 git filter-branch 또는 BFG Repo-Cleaner를 사용하여 기록을 다시 작성합니다. 단일 파일의 경우 git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch YOUR_FILE' 옵션을 사용할 수 있습니다. 이는 기록을 다시 작성하므로 주의해서 수행해야 하며, 다른 사람이 변경 사항을 가져간 경우 소통이 필요합니다.


변경 사항을 잃지 않고 마지막 커밋을 취소하려면 어떻게 해야 하나요?

답변:

git reset HEAD~1을 사용합니다. 이 명령은 HEAD 포인터를 한 커밋 뒤로 이동시키지만, 취소된 커밋의 변경 사항은 스테이징 영역 (또는 --soft가 지정되지 않은 경우 작업 디렉토리) 에 유지하여 수정 및 재커밋할 수 있도록 합니다.


잘못된 브랜치에 커밋했다면 어떻게 해야 하나요?

답변:

커밋이 가장 마지막 커밋인 경우, git reset HEAD~1을 사용하여 커밋을 취소한 다음 변경 사항을 git stash합니다. 그런 다음 올바른 브랜치로 전환하고 (git checkout correct-branch), 스테이시된 변경 사항을 적용한 다음 (git stash pop), 해당 브랜치에 커밋합니다. 대안으로 git cherry-pick을 사용하여 특정 커밋을 이동할 수 있습니다.


삭제된 브랜치를 어떻게 복구하나요?

답변:

브랜치가 최근에 삭제된 경우 git reflog를 사용하여 reflog 에서 마지막 커밋 해시를 찾을 수 있습니다. 커밋 해시를 얻으면 git branch <branch-name> <commit-hash>를 사용하여 해당 커밋에서 브랜치를 다시 생성할 수 있습니다.


로컬에 여러 커밋을 했지만, 이를 단일 커밋으로 스쿼시 (squash) 해야 한다는 것을 깨달았습니다. 어떻게 해야 하나요?

답변:

대화형 리베이스를 사용합니다: git rebase -i HEAD~N (여기서 N 은 스쿼시할 커밋 수). 대화형 편집기에서 첫 번째 커밋은 pick으로, 후속 커밋은 squash 또는 fixup으로 표시합니다. 이렇게 하면 여러 커밋이 단일 커밋으로 결합됩니다.


'detached HEAD'는 무엇을 의미하며 어떻게 수정하나요?

답변:

'detached HEAD' 상태는 HEAD 가 브랜치가 아닌 커밋을 직접 가리키고 있음을 의미합니다. 이는 특정 커밋이나 원격 태그를 체크아웃할 때 자주 발생합니다. 이를 수정하려면 현재 detached HEAD 상태에서 git checkout -b new-branch-name을 사용하여 새 브랜치를 생성합니다.


이미 푸시된 특정 커밋을 되돌리려면 어떻게 해야 하나요?

답변:

git revert <commit-hash>를 사용합니다. 이는 지정된 커밋에서 도입된 변경 사항을 취소하는 새 커밋을 생성합니다. 기록을 다시 작성하지 않으므로 공유 저장소의 무결성을 유지하면서 푸시된 커밋에 안전합니다.


실수로 대용량 파일을 저장소에 추가하고 푸시했습니다. 어떻게 제거하고 저장소 크기를 줄이나요?

답변:

먼저 git rm --cached <large-file>을 사용하여 현재 커밋에서 제거하고 커밋합니다. 기록에서 제거하려면 git filter-branch 또는 BFG Repo-Cleaner를 사용하여 기록을 다시 작성한 다음 강제 푸시합니다. 마지막으로 로컬에서 git gc --prune=now를 실행하여 느슨한 객체를 정리합니다.


Git 모범 사례 및 협업

.gitignore 파일의 목적은 무엇이며, 일반적으로 포함되는 항목은 무엇인가요?

답변:

.gitignore 파일은 Git 이 무시해야 하는 의도적으로 추적되지 않은 파일을 지정합니다. 일반적인 항목에는 빌드 아티팩트 (예: *.class, target/), 종속성 디렉토리 (예: node_modules/), 운영 체제 파일 (예: .DS_Store), 민감한 정보 (예: *.env) 가 포함됩니다. 관련 없거나 개인적인 데이터의 실수로 인한 커밋을 방지합니다.


'기능 브랜치 (feature branch)' 워크플로우의 개념을 설명하세요. 이점은 무엇인가요?

답변:

기능 브랜치 워크플로우는 각 새 기능 또는 버그 수정을 위해 새 브랜치를 생성하는 것을 포함합니다. 이는 개발 작업을 격리하여 기능이 완료되고 테스트될 때까지 기본 코드베이스에 대한 간섭을 방지합니다. 병렬 개발, 쉬운 코드 검토, 안정적인 main 또는 master 브랜치를 촉진합니다.


변경 사항을 통합할 때 git mergegit rebase 중 언제 사용해야 하나요?

답변:

git merge는 새 병합 커밋을 생성하여 변경 사항을 통합하고 원본 커밋 기록을 보존합니다. git rebase는 한 브랜치의 커밋을 다른 브랜치에 다시 적용하여 커밋 ID 를 다시 작성함으로써 선형적인 기록을 생성합니다. 기록을 유지하기 위해 공개 브랜치에는 merge를 사용하고, 푸시하기 전에 기록을 깔끔하게 유지하기 위해 로컬 비공개 브랜치에는 rebase를 사용합니다.


오픈 소스 프로젝트에 기여하기 위한 일반적인 Git 워크플로우를 설명하세요.

답변:

일반적인 워크플로우는 저장소를 포크 (fork) 하고, 로컬에서 포크를 클론하고, 새 기능 브랜치를 생성하고, 변경 사항을 만들고, 커밋하고, 포크로 푸시한 다음, 원본 저장소에 풀 리퀘스트 (pull request) 를 여는 것을 포함합니다. 그런 다음 피드백을 처리하고 병합하기 전에 커밋을 리베이스/스쿼시할 수 있습니다.


Git 훅 (hook) 이란 무엇이며, 어떻게 사용될 수 있는지 예를 들어 설명해 주세요.

답변:

Git 훅은 커밋, 푸시 또는 커밋 수신과 같은 이벤트 전후에 Git 이 자동으로 실행하는 스크립트입니다. 정책을 시행하거나 작업을 자동화할 수 있습니다. 예를 들어, pre-commit 훅은 커밋이 완료되기 전에 린터 (linter) 나 테스트를 실행하여 코드 품질을 보장할 수 있습니다.


실수로 민감한 정보 (예: API 키) 를 커밋하고 원격 저장소로 푸시한 상황을 어떻게 처리하나요?

답변:

먼저 로컬 파일에서 민감한 정보를 제거하고 .gitignore에 추가합니다. 그런 다음 git filter-branch 또는 BFG Repo-Cleaner를 사용하여 기록을 다시 작성하고 모든 커밋에서 민감한 데이터를 제거합니다. 마지막으로 원격으로 강제 푸시 (git push --force) 하고 즉시 손상된 자격 증명을 무효화합니다.


명확하고 간결한 커밋 메시지의 중요성을 설명하세요. 좋은 커밋 메시지에는 어떤 요소가 포함되어야 하나요?

답변:

명확한 커밋 메시지는 프로젝트 기록 이해, 디버깅 및 코드 검토에 매우 중요합니다. 좋은 커밋 메시지에는 변경 사항을 요약하는 간결한 제목 줄 (50-72 자) 이 있어야 하며, 그 뒤에 빈 줄이 오고, 변경된 내용과 이유를 설명하는 더 자세한 본문이 있어야 합니다. '무엇'이 변경되었는지뿐만 아니라 '왜' 변경이 이루어졌는지에 대한 답을 제공해야 합니다.


'스쿼시 커밋 (squash commit)'이란 무엇이며 언제 사용하나요?

답변:

스쿼시 커밋은 여러 커밋을 단일 새 커밋으로 결합합니다. 프로젝트 기록을 더 읽기 쉽고 간결하게 만들기 위해 main으로 병합하기 전에 지저분한 기능 브랜치 기록을 정리할 때 사용합니다. 이는 종종 대화형 리베이스 (git rebase -i) 중에 수행됩니다.


병합 충돌을 어떻게 해결하나요?

답변:

병합 충돌이 발생하면 Git 은 파일에서 충돌하는 섹션을 표시합니다. 이러한 파일을 수동으로 편집하여 유지할 변경 사항을 선택하고 Git 의 충돌 마커 (<<<<<<<, =======, >>>>>>>) 를 제거합니다. 모든 충돌을 해결한 후 수정된 파일을 git add하고 git commit하여 병합을 완료합니다.


Git 태그 (tag) 의 목적은 무엇이며 어떻게 사용하나요?

답변:

Git 태그는 일반적으로 릴리스 버전 (예: v1.0.0) 에 대해 기록의 특정 지점을 중요하게 표시하는 데 사용됩니다. 영구적인 북마크와 같습니다. git tag <tagname>(경량) 또는 git tag -a <tagname> -m 'message'(주석 포함) 로 생성하고 git push origin --tags로 푸시합니다.


'트렁크 기반 개발 (trunk-based development)'의 개념과 장점을 설명하세요.

답변:

트렁크 기반 개발은 개발자가 단일 공유 브랜치 ('트렁크' 또는 main) 에 작고 빈번한 업데이트를 병합하는 버전 제어 관리 관행입니다. 장점으로는 지속적인 통합, 더 빠른 피드백 루프, 더 작은 변경으로 인한 병합 충돌 감소, 쉬운 롤백 등이 있습니다. 강력한 테스트 자동화가 필요합니다.


Git 내부 및 아키텍처

Git 의 네 가지 핵심 객체 유형은 무엇인가요?

답변:

Git 의 네 가지 핵심 객체 유형은 blob, tree, commit, tag 입니다. Blob 은 파일 내용을 저장하고, tree 는 디렉토리 구조를 저장하며, commit 은 특정 시점의 저장소 스냅샷을 저장하고, tag 는 기록의 특정 지점을 표시합니다.


Git 에서 'blob' 객체와 'tree' 객체의 차이점을 설명하세요.

답변:

'blob' 객체는 SHA-1 해시로 식별되는 파일의 정확한 내용을 저장합니다. 'tree' 객체는 디렉토리를 나타내며, blob(파일용) 및 다른 tree(하위 디렉토리용) 에 대한 참조와 함께 이름 및 모드를 포함합니다.


Git 은 어떻게 데이터 무결성과 불변성을 보장하나요?

답변:

Git 은 모든 객체에 SHA-1 해시를 사용하여 데이터 무결성과 불변성을 보장합니다. 해시는 객체의 내용으로부터 계산되므로, 내용의 어떤 변경이라도 다른 해시를 초래하여 손상 또는 변조를 감지할 수 있습니다.


Git 에서 파일의 세 가지 주요 상태를 설명하세요.

답변:

Git 에서 파일의 세 가지 주요 상태는 다음과 같습니다: 작업 디렉토리 (수정되었지만 스테이징되지 않음), 스테이징 영역 (수정되었으며 다음 커밋을 위해 표시됨), Git 디렉토리 (커밋되어 저장소에 저장됨).


'.git' 디렉토리의 목적은 무엇인가요?

답변:

'.git' 디렉토리는 Git 저장소의 핵심입니다. Git 이 프로젝트의 기록 및 상태를 관리하는 데 사용하는 모든 필요한 객체 (blob, tree, commit), 참조 (브랜치, 태그), 구성 파일 및 로그를 포함합니다.


Git 은 전체 복사본이 아닌 파일 버전을 어떻게 효율적으로 저장하나요?

답변:

Git 은 파일이 처음 추가될 때만 전체 내용을 blob 으로 저장하여 파일 버전을 효율적으로 저장합니다. 후속 변경 사항은 새 blob 으로 저장되며, Git 은 델타 압축 (packfiles) 을 사용하여 버전 간의 차이를 저장하여 공간을 절약합니다.


Git 에서 'ref'란 무엇이며, 예를 들어 설명해 주세요.

답변:

'ref'(참조) 는 커밋 객체에 대한 포인터입니다. 일반적인 예로는 브랜치 (예: refs/heads/main), 태그 (예: refs/tags/v1.0), HEAD 가 있습니다. 이는 커밋 기록의 특정 지점에 대한 사람이 읽을 수 있는 이름을 제공합니다.


Git 에서 'HEAD'가 무엇을 참조하는지 설명하세요.

답변:

'HEAD'는 현재 작업 중인 브랜치의 최신 커밋을 가리키는 심볼릭 참조입니다. 커밋할 때 HEAD 가 가리키는 커밋 객체가 업데이트됩니다. 'detached HEAD' 상태에서는 직접 커밋 SHA 를 가리킬 수도 있습니다.


Git 에서 'packfile'이란 무엇인가요?

답변:

'packfile'은 여러 Git 객체 (blob, tree, commit) 를 압축 및 델타 인코딩된 형식으로 저장하는 Git 의 단일 바이너리 파일입니다. 이는 저장소 크기를 크게 줄이고 특히 대규모 기록의 성능을 향상시킵니다.


Git 은 내부적으로 브랜치를 어떻게 처리하나요?

답변:

Git 은 단순히 특정 커밋에 대한 새 포인터 (브랜치 ref) 를 생성하여 브랜치를 처리합니다. 커밋할 때 브랜치 포인터가 앞으로 이동합니다. 브랜치는 단순히 새 포인터이지 코드베이스의 전체 복사본이 아니기 때문에 가볍습니다.


Git 에서 'index'(또는 스테이징 영역) 란 무엇인가요?

답변:

'index' 또는 '스테이징 영역'은 Git 이 다음 커밋을 준비하는 데 사용하는 작업 디렉토리의 임시 스냅샷입니다. 다음 커밋에 포함될 파일과 해당 blob SHA-1 을 나열하는 바이너리 파일입니다.


커밋, 트리, 블롭 간의 관계를 설명하세요.

답변:

커밋 객체는 단일 트리 객체를 가리키며, 이는 해당 커밋에서 저장소 파일 및 디렉토리의 전체 스냅샷을 나타냅니다. 트리 객체는 차례로 blob 객체 (파일 내용용) 및 다른 트리 객체 (하위 디렉토리용) 를 가리킵니다.


요약

Git 면접 질문에 효과적으로 답변하는 것은 버전 관리에 대한 이해와 협업 개발 준비 상태를 증명하는 것입니다. 일반적인 시나리오와 개념적 질문에 대해 철저히 준비함으로써 기술적 숙련도뿐만 아니라 문제 해결 및 팀워크에 대한 적극적인 접근 방식을 보여줄 수 있습니다. 이러한 준비는 잠재적 고용주에게 자신의 가치를 보여주는 데 핵심입니다.

면접을 넘어 Git 숙달의 여정이 계속된다는 것을 기억하세요. 이러한 개념에 대한 지속적인 학습과 실제 적용은 기술을 공고히 하고 모든 개발 팀에 대한 기여를 향상시킬 것입니다. 새로운 기능을 수용하고, 고급 워크플로우를 탐색하며, 항상 이해도를 심화시키기 위해 노력하세요. 그러면 여러분의 경력이 보상받을 것입니다.