Git 명령어 총정리

Maru·2022년 10월 28일
0

오픈SW플랫폼

목록 보기
2/5
post-thumbnail

What is Git?

• 소프트웨어 버전관리 시스템 (Version Control System)
• 리누스가 Linux 소스코드를 관리할 목적으로 개발
• Git은 파일의 변화를 “스냅샷”으로 저장하고 현 스냅샷은 이전 스냅샷의 포인터를 가지고 있어 파일의 변경이력을 저장가능
• 스냅샷: 특정 시점에서 파일, 폴더 또는 워크스테이스의 상태
• 스냅샷을 통해 특정 시점에 저장소의 모든정보를 확인가능하 고 commit이라는 명령어를 실행하면 스냅샷이 저장됨

What is Github?

• Git을 사용하는 프로젝트 지원하고 개발자들의 버전컨트롤 및 협업을 위한 코드 호스팅 플랫폼
• 깃허브에서 제공하는 클라우드 서버를 통해 관리되는 버전관리 시스템 (웹 호스팅 서비스)

Git 설치

• Git이 설치되어있는지 확인후 설치 안되어있을경우 설치
• git --version
• [Download] https://git-scm.com/downloads

Git의 기본용어

• Repository (저장소): 소스코드가 저장되어 있는 물리적 공간
• Working Tree: 폴더를 의미
• Index (=Staging Area): Commit 전의 저장소와 Working Tree 사이에 존재하는 공간
• Commit: 변경된 작업의 점검을 마치고 저장소에 남기는 행위로 매우 중요한 단계로 Commit log가 저장됨 (e.g., git log)
• Branch: 분기점으로 작업할 때, Commit 단위로 구분된 소스코드의 현재상태를 복사 하여 Branch 에서 작업
• Checkout: 특정시점이나 특정 Branch 로 이동
• Head: 현재 작업중인 Branch
• Merge: 다른 Branch 의 내용을 현재 Branch로 가져와 병합

Repository (저장소)

• 파일이 변경이력별로 저장됨
• 저장소 종류
• Remote Repository (원격저장소): 여러사람이 함께 공유하기 위한 저장소
• Local Repository (로컬저장소): 사용자 PC에 파일이 저장되는 저장소

• 저장소 만드는 방법
• 새 저장소 생성
• 이미 존재하는 저장소를 로컬저장소로 복사

Commit (변경을 기록)

• 이전 Commit상태부터 현재상태까지의 변경 이력이 기록된 Commit이 생성
• 각 Commit은 영문/숫자 조합으로 이루어진 40개의 캐릭터 의 이름이 생성됨
• Commit 실행시 메세지를 남겨야 하고 추후 변경이력 조회시 매우 유용한 정보임 (변경내용 및 이유를 남김)

Work Tree (작업트리)/Index

• Commit을 실행하기전의 저장소와 작업 트리 사이에 존재하 는 공간을 인덱스라 함

작업트리안에 있는 파일들을 선별적으로 Commit에 포함시킬수 있음

자주 쓰는 Git 명령어

• git init: git 초기화
• git status: 현재 브랜치 이름과 추가/변경된 파일 및 디렉토리 정보 보여줌
• git add: 작업내역을 인덱스(스테이징)영역에 추가
• git commit –m “저장이름”: 커밋 생성, 변경사항 확정하여 반영
• git clone: 기존소스코드 다운로드 및 복제 (원격저장소에 로컬저장소로 카피)
• git log: 현재 커밋 목록들 확인
• git branch : branch 생성

  • git branch : 전 branch 조회
  • git branch -d : branch 삭제

• git checkout <브랜치명>

  • git checkout –b <새브랜치> <기존브랜치> : 브랜치 생성과 체크아웃을 한꺼번에 실행
  • git checkout main(master) 현재 브랜치로 돌아옴
    • git push: 소스코드의 변경사항을 원격저장소에 기록
    • git pull: 원격저장소의 변경내역이 현재 로컬저장소로 가져와서 병합함
    • git fetch: 원격저장소의 변경내역을 가져오기만하고 병합안함 (변경내용 확 인위함)
    • git merge : 작업의 마무리단계 즉 변경사항 점검 및 확정이 되면 현재 HEAD가 가리키는 브랜치에 병함됨
  • git reset: 로컬저장소의 커밋을 취소시킴
  • git branch -f main HEAD~4 : 브랜치 강제 이동

브랜치 생성

• 통합브랜치
• 배포가능한 버전으로 늘 안정적인 상태를 유지해야함
• Git 생성시 만들어지는 main 브랜치를 통합브랜치로 이용
• 토픽브랜치 (or feature branch)
• 기능추가 및 버그수정 등 단위작업을 하기위해 생성하는 브랜치
• 테스트 및 검증 후 통합브랜치로 병합됨

Pull Request 열기

• What is Pull Request (PR)?
• 브랜치를 통합브랜치에 병합하기전 거쳐야 하는 프로세스
• PR 생성시 작업한 토픽브랜치에서 변경한 사항들을 다시 한번 리뷰
• PR 생성시 검토 요청할 팀원들 추가
• PR 서브밋후 요청받은 팀원들 점검후 추가 수정사항이 있다면 코멘 트 남기고 없다면 해당브랜치를 통합브랜치에 병합함


Fork vs Clone repository

• Fork는 Github account를 사용하여 수행되는데 원격저장소의 복 사본이 Github계정에 남아있음
• Clone은 Git을 사용하여 수행되고 로컬PC에 원격저장소가 복사됨

• Fork된 저장소에서 작업후 변경사항을 원격저장소에 반영하려면 PR을 통해 수행가능함
• Clone은 저장소에서 작업후 변경사항을 원격저장소에 반영하려면 직접 Push를 통해 수행가능하지만 이때 “쓰기” 권한이 있을경우만 가능

때문에 일반적으로 Fork후 Clone을 하여 작업하는 것을 권장

  1. 원격저장소 Fork
  2. Fork된 저장소 Clone
  3. 작업후 로컬저장소 Commit
  4. 변경사항 로컬저장소 Push
  5. PR 서브밋

실습

실습

1. 커밋을 2번 하세요

git commit -m 'C2'
git commit -m 'C3' 

2. 새로운 브랜치를 만들고, 새 브랜치로 이동하기

  git checkout -b bugFix main

3. 브랜치와 합치기(Merge)

git merge입니다. Git의 합치기(merge)는 두 개의 부모(parent)를 가리키는 특별한 커밋을 만들어 냅니다. 두개의 부모가 있는 커밋이라는 것은 "한 부모의 모든 작업내역과 나머지 부모의 모든 작업, 그리고 그 두 부모의 모든 부모들의 작업내역을 포함한다"라는 의미가 있습니다.

git checkout -b bugFix main
git commit -m 'C2'
git checkout main
git commit -m 'C3'
git merge bugFix

4. Git Rebase

브랜치끼리의 작업을 접목하는 두번째 방법은 리베이스(rebase)입니다. 리베이스는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.리베이스를 하면 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점이 있습니다. 리베이스를 쓰면 저장소의 커밋 로그와 이력이 한결 깨끗해집니다.


  • 목표 : bugFix를 선택하고 main에 리베이스 하기
    git checkout -b bugFix main
    git commit -m 'C2'
    git checkout main
    git commit -m 'C3'
    git checkout bugFix
    git rebase main

5. Commit tree에서 이동 (HEAD)

먼저"HEAD"에 대해 이야기해 봅시다. HEAD는 현재 체크아웃된 커밋을 가리킵니다. -- 다시 말하자면 현재 작업중인 커밋입니다.

HEAD는 항상 작업트리의 가장 최근 커밋을 가리킵니다. 작업트리에 변화를 주는 git 명령어들은 대부분 HEAD를 변경하는것으로 시작합니다.

일반적으로 HEAD는 브랜치의 이름을 가리키고있습니다(bugFix와 같이). 커밋을 하게 되면, bugFix의 상태가 바뀌고 이 변경은 HEAD를 통해서 확인이 가능합니다.

HEAD 분리하기

HEAD를 분리한다는 것은 HEAD를 브랜치 대신 커밋에 붙이는 것을 의미합니다.
명령어 사용 전 : HEAD -> main -> C1

git checkout C1

실행 후 : HEAD -> C1

  • 목표 : HEAD를 bugFix에서 분리하고 커밋에 붙여라

    git checkout C4

    6. 상대 참조

    커밋의 해시값을 사용하는 방법은 번거롭다. 대신 상대 참조를 사용하면 편리하다.

    한번에 한 커밋 위로 움직이는 ^
    한번에 여러 커밋 위로 올라가는 ~<num>

    main^는 "main의 부모"와 같은 의미 입니다.

main^^ 는 "main의 조부모(부모의 부모)"를 의미

  • 목적
  git checkout bugFix^

틸드 "~" 연산자

git checkout HEAD~4

브랜치 강제로 옮기기

상대 참조를 사용하는 가장 일반적인 방법은 브랜치를 옮길 때 입니다. -f 옵션을 이용해서 브랜치를 특정 커밋에 직접적으로 재지정 할 수 있습니다.
(강제로) main 브랜치를 HEAD에서 세번 뒤로 옮겼습니다. (three parents behind HEAD).

git branch -f main HEAD~3
  • 문제 : 다음과 같이 만들기
 git checkout C1
  git branch -f bugFix HEAD^
  git branch -f main C6

7. Git에서 작업 되돌리기

Git에는 작업한 것을 되돌리는 여러가지 방법이 있습니다. 변경내역을 되돌리는 것도 커밋과 마찬가지로 낮은 수준의 일(개별 파일이나 묶음을 스테이징 하는 것)과 높은 수준의 일(실제 변경이 복구되는 방법)이 있는데요, 여기서는 후자에 집중해 알려드릴게요.

Git에서 변경한 내용을 되돌리는 방법은 크게 두가지가 있습니다.
하나는 git reset을 쓰는거고, 다른 하나는 git revert를 사용하는 것입니다.

Git Reset

git reset은 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌립니다. 이런 관점에서 "히스토리를 고쳐쓴다"라고 말할 수 있습니다. 즉, git reset은 마치 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것입니다.

Git Revert

각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 리셋(reset)을 잘 쓸 수 있습니다만, "히스토리를 고쳐쓴다"는 점 때문에 다른 사람이 작업하는 리모트 브랜치에는 쓸 수 없습니다.

변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 공유하기 위해서는, git revert를 써야합니다.

어색하게도, 우리가 되돌리려고한 커밋의 아래에 새로운 커밋이 생겼습니다. C2라는 새로운 커밋에 변경내용이 기록되는데요, 이 변경내역이 정확히 C2 커밋 내용의 반대되는 내용입니다. 리버트를 하면 다른 사람들에게도 변경 내역을 밀어(push) 보낼 수 있습니다.

  • 목적 : local 브랜치와 pushed 브랜치에 있는 최근 두 번의 커밋을 되돌려 보세요.

pushed는 리모트 브랜치이고, local은 로컬 브랜치임을 신경쓰셔서 작업하세요 -- 어떤 방법을 선택하실지 떠오르시죠?

git reset HEAD~1
git checkout pushed
git revert HEAD

8. Git Cherry-pick

git cherry-pick Commit1 Commit2 ...
현재 위치(HEAD) 아래로 선택한 일련의 커밋들에대한 복사본을 만드는 것입니다.


  • 목표 :

    git cherry-pick C3 C4 C7

    9. Git 인터렉티브 리베이스 (Interactive Rebase)

    원하는 커밋을 모르는 상황에는 어쩌죠? 고맙게도 git은 이런상황에 대한 대안이 있습니다. 우리는 이럴 때 인터렉티브 리베이스를 사용하면됩니다 -- 리베이스할 일련의 커밋들을 검토할 수 있는 가장 좋은 방법입니다.

인터렉티브 리베이스가 의미하는 뜻은 rebase 명령어를 사용할 때 -i 옵션을 같이 사용한다는 것입니다.

이 옵션을 추가하면, git은 리베이스의 목적지가 되는 곳 아래에 복사될 커밋들을 보여주는 UI를 띄울것 입니다. 각 커밋을 구분할 수 있는 각각의 해시들과 메시지도 보여줍니다.

git rebase -i "목적지"
"실제" git 에서는 UI창을 띄우는것 대신에 vim과 같은 텍스트 편집기에서 파일을 엽니다.

인터렉티브 리베이스 대화창이 열리면, 3가지를 할 수 있습니다:

  1. 적용할 커밋들의 순서를 UI를 통해 바꿀수 있습니다(여기서는 마우스 드래그앤 드롭으로 가능합니다)

  2. 원하지 않는 커밋들을 뺄 수 있습니다. 이것은 pick을 이용해 지정할 수 있습니다(여기서는 pick토글 버튼을 끄는것으로 가능합니다)

  3. 마지막으로, 커밋을 스쿼시(squash)할 수 있습니다. 불행히도 저희 레벨은 몇개의 논리적 문제들 때문에 지원을 하지 않습니다. 이거에 대해서는 넘어가겠습니다. 요약하자면 커밋을 합칠 수 있습니다.

  • 문제 : 다음과 같이 만들어라

  git rebase -i HEAD~4(목적지)

Git Remote(원격) 실습

실제로 git clone은 원격 저장소의 복사본을 로컬에 생성할때 사용하는 명령어입니다(github에서 가져올 때라던가). Git 브랜치 배우기에서는 이 명령어를 살짝 다르게 사용합니다 -- git clone이 당신의 로컬 저장소에서 원격 저장소를 생성해냅니다. 물론 실제 명령어와 반대로 작동하는 것이지만 클론과 원격 저장소 사이의 연결관계를 이해하는데 도움이되서 이렇게 했습니다. 일단은 그냥 해봅시다.

1. git clone

git clone

가장 먼저 알아차릴만한 변화는 우리의 로컬 저장소에 o/main라고하는 새 브랜치가 생긴겁니다. 이런 종류의 브랜치는 원격브랜치라고 불립니다; 원격 브랜치는 특정한 목적을 제공하기 때문에 특별한 속성들이 있습니다.

  1. 원격 브랜치는 원격 저장소상태를 반영합니다
    (가장 최근 원격 원격저장소와 작업을 했을때를 기준으로).
  2. 원격 브랜치는 로컬에서의 작업과 공개적으로 되고있는 작업의 차이를 이해하는데 도와줍니다
    : 다른 사람들과 작업을 공유하기전에 반드시해야할 과정이죠.

원격 브랜치는 체크 아웃을 하게 되면 분리된 HEAD 모드로 가게되는 특별한 속성이 있습니다. Git은 여러분이 이 브랜치들에서 직접 작업할 수 없기 때문에 일부로 이렇게 합니다; 여러분은 다른곳에 작업을 하고 원격 저장소와 여러분의 작업을 공유해야합니다(그 이후에 원격 브랜치가 갱신됩니다).

여러분은 원격 브랜치들 앞에 붙는 o/가 뭔지 궁금할 것입니다. 음, 원격 브랜치 또한 (필수적인) 이름짓기 규약이 있습니다 -- 다음의 형식으로 나타납니다:

<remote name>/<branch name>
이런 이유로, 만약 o/main라는 이름의 브랜치를 보게되면, 브랜치의 이름은 main이고 원격 저장소의 이름은 o인겁니다.

대부분의 개발자들은 자신의 주 원격 저장소를 o가 아닌 origin이라고 짓습니다. 사실 보통 다 이렇게 쓰기 때문에 git은 저장소를 git clone하게 되면 원격 저장소의 이름을 origin이라고 자동으로 설정해놓습니다.

보이는것 처럼, git은 우리를 분리된 HEAD 모드로 만들고 새로운 커밋을 추가해도 o/main를 갱신하지 않습니다. 이것은 o/main가 원격 저장소가 갱신될때만 갱신되기 때문입니다.

  • 문제 : main에서 한번 커밋하고 o/main를 체크아웃 하고 다시 한번 커밋

    git commit -m 'C3'
    git checkout o/main
    git commit -m 'C4' // 브랜치는 그대로, HEAD만 움직인다

    2. Git Fetch

    이번 레슨에서는 원격 저장소에서 데이터를 가져오는 방법을 배워볼 것입니다 -- 이를 위한 명령어는 git fetch라고 불립니다.
    먼저 알아두고 넘어갈것이 있는데 우리가 원격 저장소와 작업을 해서 상태가 변하면 원격브랜치들 또한 그 변경들을 반영합니다.


    커밋 C2 와 C3가 우리의 로컬 저장소로 다운로드 되었고, 원격 브랜치 o/main가 이것을 반영하기 위해 업데이트 되었습니다.

fetch는 무엇을 하는가

git fetch는 두가지의 중요한 단계를 수행합니다.
사실 이 두 단계만을 진행합니다. 그것은 :

  1. 원격 저장소에는 있지만 로컬에는 없는 커밋들을 다운로드 받습니다.
  2. 우리의 원격 브랜치가 가리키는곳을 업데이트합니다 (예를들어, o/main)
    git fetch는 본질적으로 로컬에서 나타내는 원격 저장소의 상태를 실제 원격 저장소의 (지금)상태와 동기화합니다.

fetch는 무엇을 하지 않는가

git fetch는 그러나, 여러분의 로컬 상태는 전혀 바꾸지 않습니다. 여러분의 main 브랜치도 업데이트하지 않고 파일 시스템의 모습이던 그 어떤것도 바꾸지 않습니다.

이것을 이해하는게 아주 중요한데, 왜냐하면 수 많은 개발자들이 git fetch를 하면 자신의 로컬 작업이 변경되어 원격 저장소의 모습을 반영해 업데이트 될것이라고 생각하기 때문입니다. 앞의 과정에 필요한 데이터를 다운로드는 하지만, 실제로 로컬 파일들이나 브랜치를 변경하지는 않습니다. 이것을 하기위한 명령어들은 뒤에서 배우겠습니다 :D

간단하게 git fetch를 다운로드 단계로 생각할 수 있습니다.

  git fetch
 

3. Git Pull

우리는 원격 저장소에서 git fetch로 어떻게 데이터를 내려 받는지 보았습니다. 이제 우리의 작업을 업데이트해서 변경들을 반영해 봅시다!
사실 이걸 하는 방법은 여러가지 있습니다 -- 새 커밋들을 로컬에 내려받은 이후에는 그냥 다른 브랜치에있는 일반 커밋처럼 활용할 수 있습니다. 이런 명령들을 실행할 수 있다는 뜻 입니다 :

git cherry-pick o/main
git rebase o/main
git merge o/main
기타 등등...

사실 원격 저장소의 변경을 fetch하고 그이후에 merge하는 작업의 과정이 워낙 자주있는 일이라서 git은 이 두가지를 한번에 하는 명령을 제공합니다! 이 명령어는 git pull 입니다.

  • 문제 : fetch & merge 또는 pull 사용하기

    git pull
    또는
    git fetch
    git merge o/main

    4. git fakeTeamwork (협동 가장하기, only for simulatrion)

    원격 저장소에 새로운 (가짜) 커밋을 갱신합니다. 아직 git fetch를 하지 않았기 때문에 로컬로 내려받아지지는 않았습니다.

    (https://velog.velcdn.com/images/dy6578ekdbs/post/0f88b4fd-badf-4c0e-a14c-0b2616fb4276/image.png)

  • 문제 : 원격 저장소를 하나 만들고(git clone), 원격 저장소에 몇가지 가짜 변경을 만들고 로컬에서 커밋하고 원격의 변경들을 가져오세요.

    git clone
    git fakeTeamwork main 2
    git commit -m 'C4'
    git pull

    5. Git Push


  • 문제

  git commit -m 'C2'
  git commit -m 'C3'
  git push origin main



히스토리 꼬여서 push 안될 때 - git rebase

히스토리가 엇갈렸다면 git은 여러분이 push하지 못하게 합니다.
사실 여러분이 작업을 공유하기전에 원격 저장소의 최신 상태를 합치도록 강제합니다.

  • 예시

    여러분의 최근 커밋 C3가 원격저장소의 C1을 기반으로 하기 때문에 git push가 실패합니다. 원격 저장소는 C2까지 갱신된 상태기때문에 git은 여러분의 push를 거부하게됩니다.

    그러면 이 상황을 어떻게 해결할까요?
    쉽습니다, 여러분의 작업을 원격 브랜치의 최신상태를 기반으로 하게 만들면 됩니다.

이렇게 하기위한 방법이 여러가지가 있는데, 가장 간결한 방법은 리베이스를 통해 작업을 옮기는 방법입니다. 예제를 통해 눈으로 확인해 봅시다.





꼬였을 때 - Git Merge

git merge가 여러분의 작업을 옮기지는 않지만(merge 커밋을 생성합니다). git에게 원격 저장소의 변경을 합쳤다고 알려주는 방법중에 하나입니다. 이제 원격 브랜치가 여러분 브랜치의 부모가 되었기때문입니다, 여러분의 커밋이 원격 브랜치의 모든 커밋을 반영했다는 뜻이죠.


git pull이 fetch와 merge의 줄임 명령어라는 것은 이미 알고 있을 것입니다.
아주 간단하게, git pull --rebase를 하면 fetch와 리베이스를 하는 작업의 줄임 명령어 입니다

  • 일반 pull만 한 경우

  • 문제

    여러분의 저장소를 clone 하세요
    가짜 팀워크를 만드세요 (1개의 커밋)
    여러분의 작업도 커밋하세요 (1개의 커밋)
    여러분의 작업을 리베이스를 통해 공유하세요

    git clone
    git fakeTeamwork main 1
    git commit -m 'C3'
    git fetch
    git rebase o/main
    git push 
profile
함께 일하고 싶은 개발자

0개의 댓글