본문 바로가기
개린이 이야기

Git에 관하여

by iOS 개린이 2023. 6. 25.

Git이란?

Git은 분산 버전 관리 시스템 중 하나로, 소스 코드의 변경 사항을 효과적으로 추적하고, 관리할 수 있게 해주는 도구이다.

Git은 프로젝트 내의 파일 변경 내역을 저장하고, 여러 사람들이 동시에 협업하면서도 코드의 일관성을 유지할 수 있도록 도와준다.

 

버전 관리 시스템이 필요한 이유

1. 변경 이력 추적

프로젝트의 파일들에 대한 변경 이력을 추적할 수 있다. 이를 통해 누가 언제 어떤 변경을 했는지 파악할 수 있다.

 

2. 코드 복구

만약 실수로 중요한 코드를 지웠거나, 특정 시점으로 코드를 되돌리고 싶을 때, 버전 관리 시스템을 통해 이전 상태로 쉽게 되돌릴 수 있다.

 

3. 협업 강화

여러 사람들이 동시에 같은 코드베이스에서 작업할 때, 서로의 작업을 병합하고 충돌을 해결하는 과정을 원활하게 만들어준다.

 

 

Git의 핵심 개념

1. 스냅샷(Snapshot)

Git은 파일을 저장할 때, 단순히 파일의 사본을 저장하는 것이 아니라, 특정 시점에 대한 프로젝트의 '스냅샷'을 기록한다.

즉, 어느 시점에 파일들의 상태를 그대로 찍어 기록하는 것이다.

 

2. 커밋(Commit)

작업 내용을 저장하는 행위를 말한다. 커밋을 하면 해당 시점의 스냅샷이 기록되며, 고유한 해시 값이 부여된다.

이 해시 값을 통해 우리는 특정 커밋으로 이동할 수 있다.

 

3. 리포지토리(Repository)

Git에서 프로젝트를 관리하는 저장소를 말한다. 리포지토리에는 프로젝트의 모든 파일과 각 파일의 변경 이력이 포함되어 있다. 리포지토리는 원격(remote) 또는 로컬(local)에 존재할 수 있다. 원격 리포지토리는 여러 사람들과 협업하는데 사용되며, 로컬 리포지토리는 개발자의 개인 컴퓨터에 위치한다.

 

 

Git의 기본 명령어

1. git init

git init

 

새로운 Git 리포지토리를 초기화하는 명령어이다. 이 명령을 실행하면 현재 디렉토리에 '.git' 이라는 하위 디렉토리가 생성되고, 여기에 Git 관련 데이터와 설정 정보가 저장된다.

 

2. git add

git add <파일 이름>

 

변경된 파일을 Git의 Staging area에 추가하는 명령어이다. Staging area는 커밋을 준비하는 공간으로, 여기에 추가된 파일만이 실제로 커밋될 때, 리포지토리에 반영된다.

 

*Staging area가 필요한 이유

1) 선택적 커밋

Staging area를 이용하면 변경된 모든 파일을 한 번에 커밋하지 않고, 선택적으로 일부 파일만 커밋할 수 있다.

예를 들어, 한 기능과 무관한 여러 버그를 수정했을 때, 별도의 커밋으로 분리하여 기록할 수 있다. 이를 통해 커밋 로그를 더 명확하게 하면서, 추후 코드를 검토하는데 도움이 된다.

 

2) 커밋 전 검토

변경 사항을 커밋하기 전에 Staging area에 추가함으로써, 어떤 변경 사항이 커밋될지 미리 확인하고 검토할 수 있다.

이를 통해 실수로 불필요한 파일을 커밋하는 것을 방지할 수 있으며, 의도한 대로 변경 사항이 기록되는지 확인할 수 있다.

 

3. git commit

git commit -m "커밋 메세지"

 

Staging area에 올라와있는 파일들을 리포지토리에 영구적으로 저장해주는 명령어이다.

커밋은 프로젝트의 특정 시점을 기록하는 것으로, 이를 통해 이후에 특정 상태로 되돌아 갈 수 있다.

 

4. git status

git status

 

현재 리포지토리의 상태를 확인하는데 사용되는 명령어이다.

변경된 파일, Staging area에 추가된 파일, 커밋되지 않은 변경사항 등을 볼 수 있다. 

 

5. git log

git log

 

리포지토리의 커밋 이력을 확인하는데 사용되는 명령어이다.

최신 커밋부터 시작하여 이전 커밋들의 정보(해시, 저자, 날짜, 커밋 메시지)를 확인할 수 있다.

 

 

원격 리포지토리 관련 명령어

1. git clone

git clone <원격 리포지토리_URL>

 

원격 리포지토리를 복사하여 로컬에 새로운 디렉토리를 생성해주는 명령어이다.

원격 리포지토리의 모든 데이터를 로컬에 가져오며, 원격 리포지토리를 추적하는데 사용된다.

 

2. git remote

원격 리포지토리 추가

git remote add <별칭> <원격 리포지토리_URL>

 

원격 리포지토리 목록 확인

git remote -v

 

원격 리포지토리와 연결을 해주는 명령어이다.

원격 리포지토리의 별칭을 추가하거나 확인할 수도 있다.

 

3. git push

git push <원격 리포지토리_별칭> <브랜치 이름>

 

로컬 리포지토리의 변경 사항을 원격 리포지토리에 업로드하는 명령어이다.

일반적으로 작업을 완료한 후에 원격 리포지토리에 변경 사항을 공유하기 위해 사용된다.

 

4. git pull

git pull <원격 리포지토리_별칭> <브랜치 이름>

 

원격 리포지토리의 최신 변경 사항을 로컬 리포지토리로 가져오는 명령어이다.

이는 원격 리포지토리의 변경 사항을 로컬로 병합하는 과정을 포함한다.

협업할 때, 다른 사람들의 변경 사항을 로컬에 반영하기 위해 사용된다.

 

 

브랜치(Branching)와 병합(Merging)

브랜치(Branching)

브랜치는 독립적인 코드 작업을 할 수 있도록 해준다. 기본적으로 Git 리포지토리에는 'master' 또는 'main' 이라는 기본 브랜치가 있다. 새로운 기능 개발이나 버그 수정을 진행할 때, 기본 브랜치에서 분기하여 새로운 브랜치를 생성하고, 새로운 브랜치에서 작업을 진행하는 것이 좋다. 이렇게 하면 메인 코드와 독립적으로 작업할 수 있으며, 작업이 완료되면 다시 메인 브랜치에 병합할 수 있다.

 

1. git branch

브랜치 생성

git branch <브랜치_이름>

 

브랜치 목록 확인

git branch

 

브랜치를 생성하거나 목록을 확인하는데 사용되는 명령어이다.

 

 

2. git checkout

브랜치 전환

git checkout <브랜치_이름>

 

새 브랜치 생성 및 전환

git checkout -b <브랜치_이름>

 

특정 브랜치로 전환하는데 사용되는 명령어이다.

 

 

병합(Merging)

병합은 두 개의 브랜치를 합치는 것이다. 일반적으로 새로운 기능이나 수정 사항을 개발 브랜치에서 작업한 후, 이를 메인 브랜치에 병합한다. 병합 과정에서는 두 브랜치의 변경 사항을 통합하며, 때때로 충돌이 발생할 수 있다. 이 경우, 수동으로 충돌을 해결한 후 병합을 완료해야 한다.

 

1. git merge

git checkout main
git merge feature

 

브랜치를 병합하는데 사용되는 명령어이다.

사용 방법은 먼저 병합할 대상 브랜치로 전환한 후, 해당 명령어를 실행한다.

위 코드는 'feature' 브랜치를 'main' 브랜치에 병합하는 경우이다.

 

 

충돌(Conflict)

두 브랜치의 변경 사항을 통합하는 경우, 때때로 충돌이 발생할 수 있다고 했죠?

충돌이 발생하는 주된 이유는 여러 사람이 동시에 같은 코드베이스에서 작업하고, 서로 다른 변경 사항을 만들 때, 이 변경 사항들이 서로 호환되지 않기 때문이다. Git은 자동으로 코드를 병합할 수 있는 경우가 많지만, 종종 어떤 변경 사항이 올바른지 판단할 수 없는 상황이 발생한다.

 

1. 동일한 줄 수정

두 명 이상의 개발자가 동시에 같은 파일의 동일한 줄을 수정했을 때, Git은 어떤 변경 사항을 채택해야 할 지 알 수 없다.

이런 경우, 어떤 버전을 선택할 지 개발자에게 선택권을 준다.

 

2. 한 사람은 수정하고, 다른 사람은 삭제

한 명의 개발자가 파일의 특정 부분을 수정하면서, 다른 개발자가 동일한 부분을 삭제한 경우 충돌이 발생할 수 있다.

 

3. 중첩된 브랜치 변경 사항

두 개의 브랜치에서 서로 다른 변경 사항이 중첩되어 발생하는 경우 충돌이 발생할 수 있다.

예를 들어, 한 브랜치에서 함수의 이름이나, 매개변수를 변경하고, 다른 브랜치에서는 함수의 본문을 수정하는 경우, 두 변경 사항이 서로 호환되지 않을 수 있다.

 

충돌 해결

1. 충돌 감지

먼저 Git에서 충돌을 감지하면 병합 작업이 중단된다. 이 경우, 'git status' 명령어를 사용하여 충돌 상태를 확인할 수 있다.

 

2. 충돌 파일 수정

Git은 충돌 부분을 '<<<<<<', '======', '>>>>>>'로 표시해준다. 

이 부분들 사이에는 각 브랜치에서의 변경사항이 표시된다.

 

<<<<<<< HEAD

// main 브랜치의 코드
print("Hello, World!")

=======

// feature 브랜치의 코드
print("Hello, Git!")

>>>>>>> feature

 

여기서 우리는 두 변경 사항 중 하나를 선택하거나, 새로운 코드로 변경하여 충돌을 해결해야 한다.

print("Hello, Git World!")

 

3. 충돌 해결 커밋

파일을 수정한 후, 충돌이 해결되면 'git add' 를 사용하여 수정된 파일을 스테이징 영역에 추가한다.

그리고 'git commit' 을 사용하여 충돌을 해결한 내용을 커밋한다.

 

4. 병합 완료

충돌을 해결하고 커밋을 완료하면, 병합 과정이 완료된다.

 

 

Rebase

Git에서 브랜치를 관리하는 또 다른 기술로, 특정 브랜치의 커밋을 다른 브랜치 위로 이동시키는 것이다. 보통 커밋 이력을 재정렬하여 깔끔하게 관리하는 경우에 사용된다.

 

git checkout branchA //브랜치 A에서 작업 중

git rebase branchB //브랜치 B를 기준으로 브랜치 A를 rebase

 

작동 방식

1. 브랜치 A에서 작업을 하고 있고, 브랜치 B에 이를 Rebase 한다.

2. Git은 브랜치 A의 커밋 이력에서, 브랜치 B가 생성(분기)된 시점 이후로 생성된 커밋들을 임시로 저장한다.

3. 브랜치 A의 커밋을 브랜치 B의 최신 커밋으로 이동시킨다.

 

이 과정을 거치면 브랜치 A의 커밋들이 브랜치 B 위로 이동되고, 브랜치 A의 커밋들이 브랜치 B의 최신 상태 위에 놓이게 된다.

 

여기서 주의해야 할 점은 master 브랜치에서 다른 브랜치를 기준으로 Rebase를 하는 것이다. 

master 브랜치에서 다른 브랜치를 기준으로 Rebase를 하는 경우 master 브랜치의 커밋 이력들이 변경되기 때문에 기준점을 잘 설정하는 것이 중요하다.

 

 

Reset

git Reset

이 명령어는 주로 브랜치의 HEAD와 인덱스(Staging area)를 특정 상태로 되돌리는데 사용된다.

 

최근의 커밋들을 취소하고, HEAD와 현재 브랜치를 이전의 커밋으로 이동시킬 수 있다. 이는 실수로 잘못된 커밋을 했을 때, 유용하다. 또한 작업 디렉토리의 변경 사항을 Staging Area에서 제거하는 데도 사용된다. 

 

1. Soft

git reset --soft [커밋]

 

Soft reset은 HEAD를 지정된 커밋으로 이동시키지만, Staging area와 작업 디렉토리는 그대로 유지한다.

이를 통해 새로운 커밋을 생성하기 전, 변경 사항을 유지할 수 있다.

 

2. Mixed

git reset --mixed [커밋]

 

HEAD를 지정된 커밋으로 이동시키고, Staging area를 해당 커밋 상태로 되돌린다.

하지만 작업 디렉토리의 변경 사항은 그대로 유지된다. 

이 옵션은 기본적으로 사용되며, 따로 지정하지 않으면 Mixed reset이 실행된다.

 

3. Hard

git reset --hard [커밋]

 

Head를 지정된 커밋으로 이동시키고, Staging area, 작업 디렉토리 모두를 해당 커밋 상태로 되돌린다.

이 경우, 변경 사항을 완전히 버리는데 사용되므로 주의가 필요하다.

 

*HEAD란

현재 체크아웃된 커밋을 가리키는 포인터이다.

즉, 현재 작업 중인 브랜치의 가장 최근 커밋을 나타낸다.

 

 

Revert

git revert

git revert는 취소하고 싶은 특정 커밋의 내용을 되돌리는 새로운 커밋을 만든다.

그러나 'git reset' 과 달리 'git revert'는 히스토리를 수정하거나 삭제하지 않는다. 대신, 새로운 커밋을 생성하여 이전 커밋에서 했던 변경 사항을 되돌린다. 

이를 통해 히스토리가 유지되면서도 이전 커밋의 변경 사항을 취소할 수 있다.

 

git revert <커밋_해시값>

 

 

Reset과 Revert

Reset

되돌려야 하는 커밋이 로컬에만 존재하는 경우에 사용해야 한다.

Reset은 해당 커밋을 아예 삭제하고, 커밋 기록을 변경하기 때문에 같이 협업하고 있는 팀원의 작업에도 영향일 끼칠 수 있다. (협업하는 프로젝트 브랜치에 reset을 실행하면, 다른 팀원이 새로운 커밋을 push할 때, 브랜치에 충돌이 난다.)

따라서 아직 원격 리포지토리에 push하지 않은 커밋들을 수정하거나 삭제할 때 유용하다.

 

Revert

반면에 Revert는 변경 내용을 취소하는 새로운 커밋을 생성하여 사용하기 때문에, 변경 사항을 안전하게 되돌릴 수 있으며, 커밋 기록도 유지할 수 있다.

 

 

Stash

작업 중인 변경 사항을 일시적으로 저장해두고, 나중에 다시 적용할 수 있도록 해주는 명령어이다.

예를 들어, 현재 브랜치에서 작업 중인데, 급하게 버그 수정을 위해 다른 브랜치로 전환해야 할 때, 또는 작업 중인 코드가 아직 커밋을 할 만큼 완성되지 않았을 때 사용한다.

 

1. git stash save, git stash

현재 작업 디렉토리의 변경 사항을 일시적으로 저장한다. 

 

2. git stash list

여러 개의 'stash'를 만들 수 있는데, 이 명령어를 통해 저장된 'stash' 목록을 볼 수 있다.

 

3. git stash apply

가장 최근에 저장한 'stash' 의 변경 사항을 현재 작업 디렉토리에 다시 적용한다. 해당 'stash'는 목록에 그대로 남아있음.

 

4. git stash pop

가장 최근에 저장한 'stash' 의 변경 사항을 현재 작업 디렉토리에 다시 적용하고, 해당 'stash'를 목록에서 제거한다. 

 

5. git stash drop <stash_id>

특정 'stash'를 목록에서 제거한다. 각 'stash'의 id는 'git stash list'를 통해 알 수 있다.

 

6. git stash clear

모든 'stash' 를 제거하는 명령어.

 

7. git stash branch <branchname>

'stash' 를 새 브랜치에 적용하면서, 새로운 브랜치를 생성한다.

복잡한 충돌을 피하거나, 변경 사항을 별도의 브랜치로 관리하고자 할 때 유용하다.

 

 

 

git ignore

'git ignore' 파일은 특정 파일이나 디렉토리를 무시하도록 설정하는데 사용된다.

프로젝트를 개발하면서, 모든 파일을 관리할 필요는 없으며, 일부 예민한 파일은 공유하거나 저장소에 올리지 않아야 한다.

 

git ignore 파일의 구문

1. 해시(#)

# 주석

 

해시로 시작하는 라인은 주석으로 취급된다.

 

2. 슬래시(/)

/logs

 

슬래시로 시작하는 라인은 해당 디렉토리를 무시한다.

코드는 'logs' 라는 디렉토리를 무시하도록 한다.

 

3. 별표(*)

*.log

 

별표는 여러 파일을 일치시키는 데 사용할 수 있다.

코드는 '.log' 확장자를 가진 모든 파일을 무시하도록 한다.

 

4. 느낌표(!)

!/logs/important.file

 

느낌표는 특정 파일을 무시하지 않도록 제외해준다. 

코드는 'logs' 파일 내의 'important.file' 이 무시되지 않도록 한다.

 

 

트러블 슈팅과 사고의 흐름

1. 문제 인식

Git을 사용하면서 발생한 구체적인 문제나 어려움을 명확하게 기술한다. 예를 들어, 병합 충돌이 발생하거나, 특정 커밋을 잘못 적용한 경우 등이 있다.

 

2. 분석 및 사고 과정

문제를 해결하기 위해 어떤 단계를 거쳤는지, 어떤 자료를 찾아보았는지를 기술한다. 이를 통해 문제를 분석하고 해결책을 찾기 위한 논리적 사고 접근을 보여줄 수 있다.

 

3. 해결책

문제를 해결한 방법과 그 이유를 설명한다. 어떤 명령어를 사용했는지, 어떤 설정을 변경했는지, 또는 팀원과 함께 문제를 해결하기 위해 어떻게 협력했는지 등을 작성한다.

 

4. 결과 및 배운 점

문제 해결을 통해 얻은 결과와 앞으로 비슷한 문제를 피하거나 더 효과적으로 해결하기 위해 배운 점을 기록한다.

 

 

 

Reference

https://velog.io/@njs04210/Git-reset%EA%B3%BC-revert-%EC%95%8C%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

https://www.freecodecamp.org/korean/news/giteseo-keomis-doedolrigi-majimag-keomiseul-cwisohaneun-bangbeob/

'개린이 이야기' 카테고리의 다른 글

MVVM(Model-View-ViewModel)에 관하여  (0) 2023.07.12
Git Flow에 관하여  (0) 2023.06.26
Swift의 API Design Guidelines  (0) 2023.06.12
Protocol과 associatedtype에 관하여  (0) 2023.06.06
Protocol Composition에 관하여  (0) 2023.06.06