Git

newhyork·2022년 5월 15일
0

commands


git config --global (user.name <user_name>/user.email <user_email>)

사용자가 저장소에 코드를 반영할 때 등록될 사용자 정보를 설정한다.

  • 프로젝트마다 다른 사용자 정보로 지정하고 싶으면, --global 옵션을 제거한다.
  • 설정 정보는 git config --list로 확인한다.

git init

현재 디렉터리를 git repository(깃 저장소)로 만든다.

  • 현재 디렉터리에 .git 디렉터리가 생성되며,
    .git 디렉터리 이외의 영역을 working directory라고 한다.
  • git repository인 디렉터리에서는,
    working directory에서 작업을 하고 그 작업 내역을 git repository에 반영하며,
    commit 등에 의해 반영된 version은 모두 .git 디렉터리에 저장되어
    version 관리를 할 수 있게 된다.
  • .git 디렉터리 안에는 commit 등을 했을 때의 version을 비롯하여
    해당 git repository에 관한 각종 데이터가 담겨있다.

git add <file_name>

working directory에서 파일을 수정한 내역을 git repository에 반영하기 전에
staging area(준비 영역)에 올린다. (staging area는 index나 cache라고도 한다.)

  • 파일이름 대신 ‘*(모든 파일)’ 이나 ‘.(현재 디렉터리)’을 사용할 수 있다.
    (’*’ 사용 시 .gitignore에 있는 것들도 올라갈 수 있으니, ‘.’을 사용하도록 한다.)
  • 여러 개를 하려면 띄어쓰기로 구분한다.

git status

staging area에 어떤 파일이 어떻게 올라가 있는지 확인한다.

  • 파일은 크게 다음과 같은 상태로 분류된다.
    • untracked: 한 번도 commit 되지 않음. add부터 해야 함.
    • staged: add 후 commit 되기를 기다림.
    • unmodified: commit 후 수정되지 않음.
    • modified: commit 후 수정됨. add를 해야 함.

git commit -m <commit_message>

staging area에 있는 수정 내역이 있는 파일들을 repository에 반영한다.

  • --amend: 최근 commit과 관련하여 message에 오타 혹은 누락된 파일이 있을 때 사용.
  • untracked가 아니라면, -a 옵션을 추가하여 add와 commit을 동시에 할 수 있다.

git restore <file_name>

commit 이후 working directory에서 수정한 파일을 다시 원래대로 복구할 때 쓴다.

  • 즉, working directory에서 수정한 내역 중 staged가 아닌 파일들을 복구한다.
  • --staged: staged인 파일들을 unstaged로 내린다.

git clean

Untracked files을 제거할 때 사용한다

  • 다양한 옵션이 있는데, -fd를 사용하여 파일 및 디렉터리를 삭제한다.

git diff

현재 수정하고 있는 파일들 중 commit한 것들의 수정 내역을 확인한다.

  • conflict가 발생했을 때 주로 사용한다.
  • --staged: commit한 것과 staging area를 비교한다.

git log

repository의 반영 내역, 즉 commit에 따른 모든 version을 확인할 수 있다.

  • <branch_name>: 특정 branch에 관계된 commit log만 확인한다.
  • -p, --patch: 각 commit에 대한 수정 내역을 확인할 수 있다.
    (diff 와 비슷하다.)
  • --stat: 각 commit에 대해 어떤 파일이 수정되었는지 확인할 수 있다.
  • --oneline: 각 commit을 한 줄로 간단하게 보여준다.
    (commit id는 맨 앞 7자로 줄여 쓰곤 한다)
  • --graph: 각 commit간의 연결 관계를 그래프로 확인할 수 있다.
  • -S <string>: 각 commit의 수정 내역에서 특정 string이 포함된 것들만 골라 확인할 수 있다.
  • git config --global alias.l ‘log --oneline --all’을 통해 git l 등으로 줄여 쓰곤 한다.
  • (git reflog: git command log를 모두 확인할 수 있다.)

git reset <commit id>

이전 commit으로 되돌아간다.
이후의 commit 작업 내역들은 옵션에 따라 유실되거나 다른 상태가 된다.

  • default는 --mixed로, 이후 commit된 것과 작업 중인 것들을 unstaged로 둔다.
  • --soft: 이후의 commit들은 staged로, 작업 중이던 것들은 unstaged로 둔다.
  • --hard: 이후의 commit과 작업 중인 것들을 모두 버린다.
    --soft와는 달리, commit한 파일을 삭제했을 때도 복구할 수 있다.
  • <commit id> 대신 @~N을 사용하기도 한다.
    @: HEAD를 나타낸다.
    ~: 이전 commit을 가리킬 때 사용한다.
    ^: 병합된 branch에 있는 이전 commit을 가리킬 때 사용한다.
  • <commit id>대신 <file_name>을 쓴다면 git restore --staged 와 같다.
    staging area에서 unstaged(untracked/modified)로 내린다.
  • Untracked인 것들은 영향이 없으므로, git clean을 사용해야 한다.

git revert <commit id>

이전의 특정 commit에서 작업한 내역을 취소하고 다시 작업하고자 할 때 쓴다.

  • reset과 달리, 돌아간 commit 이후의 commit들은 유실되지 않고 그대로 남아 있다.
    따라서 이후의 commit들에 대한 작업 내역은 남아있다.
    해당 commit에서 작업한 내역만 취소되는 것이다.
  • remote와 관련하여 push한 commit이 있는 branch에서,
    reset으로 인한 conflict를 방지하기 위해 reset 대신 사용한다.
    1. git revert <commit id>로 현재 commit에서 이전 commit으로 되돌아간다.
      (이 때, conflict가 발생할 수도 있다.
      revert한 commit에서 작업한 파일을 이후의 commit에서도 수정했기에 발생하는 것이다.
      conflict를 해결하고 add, git revert --continue를 한다)
    2. 해당 commit에서 작업한 내역이 취소된 것으로 새로운 commit이 생성된다.
    3. 이후 작업을 한다.
      (revert 시 --no-commit 옵션을 주어, 2에서 바로 commit이 되지 않게 할 수 있다.
      즉, 해당 commit에서의 작업이 취소된 것으로 staged인 상태가 된다.)

branch


git branch <branch_name>

현재 버전에서 가지를 뻗어 독립적으로 작업을 진행한다.
이후, merge를 통해 병합하곤 한다.

  • 이슈를 해결하거나 새로운 기능을 추가하고자 할 때 쓴다.
  • <branch_name>을 생략하면, 현재 git repository에 있는 branch를 확인할 수 있다.
  • -d: 해당 branch를 삭제한다.

git checkout <branch_name>

HEAD pointer가 가리키는 것을 변경함으로써 branch를 전환한다.

  • <branch_name> 대신 snapshot hash code를 직접 가리킬 수도 있다.
    하지만, 이 때는 HEAD가 detached 상태가 된다.
    이 상태에서 commit하는 것은 불안정한 것으로,
    보통 실험적인 것들을 시도할 목적으로 하곤 한다.
    물론, 이 상태에서 commit한 것들을 저장하기 위해
    새로운 branch를 생성하며 이동할 수도 있고,
    혹은 이동 후에 새로운 branch를 생성하여 해당 commit들을 할당할 수도 있다.
  • git의 버전이 업데이트 됨에 따라,
    checkout 대신 switch을 사용하는 추세이다.
  • -: 이전 branch로 이동한다.

git merge <branch_name>

해당 <branch_name>에서 작업한 commit 등의 내역을 현재 branch에 병합한다.

  • 기준 branch는 지금까지의 작업 내역을 누적해서 저장할 것이고,
    병합될 branch는 <branch_name>으로, 기준이 되는 branch에서 파생된 것이다.
  • fast forward
    • 기준이 되는 master branch 등에서 어떤 branch를 생성하여 작업을 하고
      기준 branch에서는 이후 딱히 수정된 내역이 없을 때,
      생성한 branch를 기준 branch에 merge하기 위해 사용하는 방법이다.
      이 병합은 그저, 동일한 commit을 가리키도록 이동 시키는 것에 불과하다.
    • master branch에서 A branch를 생성했다고 가정한다.
    1. A branch로 이동하여 commit 등 작업을 한다.
    2. 작업을 끝냈으면, master branch로 이동한다.
    3. git merge A로 A branch에서의 작업 내역들을 master branch에 병합한다.
    4. A branch와 master branch는 서로 동일한 commit을 가리킨다.
  • 3-way merge
    • 마찬가지로 기준 branch에서 어떤 branch를 생성하여 작업을 하고,
      기준 branch에서도 이후 commit 등 수정 내역이 있을 때,
      생성한 branch를 기준 branch에 merge하기 위해 사용하는 방법이다.
      즉, 현재 branch가 가리키는 commit이
      merge할 branch의 ancestor이 아닌 것이다.
      그러므로 Git은, 각 branch가 가리키는 commit 2개와
      common ancestor을 사용하여, 3-way merge를 한다.
      이는, merge 결과를 별도의 commit으로 만들고 나서
      기준 branch가 그 commit을 가리키도록 이동 시킨다.
      결과적으로 그 merge commit은 부모가 여러 개가 된다.
    • master branch에서 A branch를 생성했다고 가정한다. (C2)
      (이 때, C2가 common ancestor인 commit이다.)
    1. A branch로 이동하여 commit 등 작업을 한다. (C3)
    2. 작업을 끝냈으면, master branch로 이동하여 작업을 한다. (C4)
    3. 작업을 끝내고, git merge A로 master branch에 병합한다.
    4. master branch는 merge 결과로, C5를 가리킨다.
      A branch는 그대로, C3를 가리킨다.
  • merge conflict
    merge를 시도한 두 branch에서 같은 파일을 작업하여,
    수정한 부분의 내용이 달라 충돌을 일으키는 것이다.
    • 해결 방법
    1. git status를 통해 어느 파일에서 충돌이 발생했는지 확인하여, 열어본다.
    2. 기준 branch인 HEAD의 version과 병합할 branch의 version의 작업 내역을
      살펴보아 서로 잘 반영하고, <<<, ===, >>> 행을 삭제하여 충돌을 해결한다.
    3. 충돌을 해결했으면 add, commit 한다.
  • merge는, commit 내역이 모두 그대로 남고
    3-way merge의 경우 merge commit이 새로 생긴다는 특징이 있다.
    (참고로 merge commit은, 해당 remote branch에 대한 push event이다.)
    이러한 불필요한 commit은 history를 지저분하게 하여 협업 시 불편하다.
    그래서 rebase와 squash를 통해 merge를 하곤 한다.
    • 프로젝트의 commit history를 어떤 관점으로 바라보고 관리하는 지에 따라
      단순히 merge만 하거나 rebase/squash를 혼용하여 사용한다.
      • 작업한 사실을 중요하게 다룰 때는 merge.
      • 진행 과정을 다듬어서 보여주기 위함이면 rebase.

git rebase <branch_name>

기준 branch의 base를 다른 commit으로 재설정한다.

  • 3-way merge를 해야할 때, merge commit이 발생하지 않게 하기 위해 사용한다.
    여러 commits을 통합하는 squash를 할 때도 rebase를 쓰는 것이긴 하다.
  • 3-way merge의 상황과 마찬가지로 common ancestor을 갖는 두 branch에서,
    기준 branch의 base를 <branch_name>의 최신 commit으로 전환하는 것이다.
    즉, 결과적으로 두 branch가 합쳐져 log graph 상으로 일렬이 되는데
    두 branch의 common ancestor인 기준 branch의 base commit 이후에는
    <branch_name>에서 작업한 commit이 뒤따라오고,
    기준 branch에서 작업한 commit들은
    수정 내역은 그대로 이지만 새로운 commit id를 갖게 된다.
    • master branch에서 A branch를 생성했다고 가정한다. (C2)
      (이 때, C2가 common ancestor인 commit이다.)
    1. A branch로 이동하여 commit 등 작업을 한다. (C3)
    2. 작업을 끝냈으면, master branch로 이동하여 작업을 한다. (C4)
    3. 작업을 끝내고, git rebase A로 master branch에 병합한다.
    4. master branch는 rebase 결과로, 작업 내역은 그대로 이지만
      원래 가리키던 C4가 사라지고 새로운 C5를 생성하여 가리킨다.
      A branch는 그대로, C3를 가리킨다.
      log graph는 master branch와 A branch가 일렬로 되어 있다.
      기준 branch의 원래 base (C2) 이후로는
      우선 A branch에서 작업했던 내역(C3)이 모두 뒤따라 오고,
      master branch에서 작업한 내역(C4)은 그 이후에 온다.
  • squash
    commit 내역을 하나로 통합하고자 할 때 사용하는 방법이다.
    • 하나로 통합하게 되어 나머지 commit message가 유실된 것처럼 보이나,
      따로 tracking하여 확인할 수는 있다.
      1. git rebase의 -i 옵션을 이용한다.
        git rebase -i <commit id> 혹은 git rebase -i @~3 과 같이 사용한다.
      2. editor창 등이 뜨면 각 commit을 어떻게 할 것인지 결정할 수 있다.
        합쳐서 없앨 commit을 pick에서 s(squash)로 수정한다.
        (이 때, editor로 commit_editmsg이 뜨면 잘 되지 않으니,
        git config -e --global 후, editor를 vim으로 변경해주자.)

        합쳐질 때의 commit message도 변경할 수 있다.
    • rebase를 이용한 것이므로, 새로운 commit id를 생성하여 가리킨다.
  • remote와 관련되지 않은 local branch에서,
    독립적으로 작업할 때 사용해야 안정적이다.
    rebase는 새로운 commit이 생성되어 전환되는 방식이기 때문이다.
    • 즉 remote에 push한 commit이 있는 branch에서는,
      rebase를 사용할 때 commit id가 변경된다는 점에서
      추후 push를 하고 pull을 할 때 conflict가 발생하는 문제가 있으므로
      잘 사용하지 않는다.
    • 따라서 local에서 작업을 하고 remote로 push하기 전,
      commit을 정리하는 차원에서 이용하는 것을 목적으로 한다.
  • 보통 PR(/MR) 직전까지는 rebase, 이후 PR로 merge하는 방식으로 섞어 쓴다.

git stash

현재 작업 중인 내역을 commit을 하지 않고 임시로 저장해두고 다른 branch이동할 때 사용한다.

  • working directory에서 수정한 내역들만 저장한다.
    즉, modified이거나 staged 상태인 파일.
  • -u: untracked인 파일도 함께 임시 저장한다.
  • -m <stash_message>: stash 시 message를 작성하여 저장한다.
  • git stash list: 목록을 확인한다.
    • stack 자료구조이므로, 0번째가 가장 최근 것이다.
    • stash list는 현재 branch 위치 등에 관계없이 공유된다.
  • git stash clear: stash stack을 모두 제거한다.
  • git stash pop <stash_name>: stash를 적용함과 동시에 제거할 수 있다.
    • stash를 생성한 브랜치로 이동해서 사용하도록 한다.
      다른 브랜치에서 pop을 하면, conflict가 발생할 수 있으므로 주의한다.
    • --index 옵션을 주어, staged인 것까지 복원한다.
    • git stash apply는 단순히 stash의 내용을 가져온다.
    • git stash drop은 단순히 stash를 제거한다.
  • git stash show <stash_name>: stash에 저장된 내역을 확인할 수 있다.

remote repository


git remote add <remote_repo_name> <remote_repo_path>

local repository에서 remote repository에, 특정 이름으로 연결한다.

  • git remote -v: 어떤 remote repository들이 연결됐는지 확인한다.
  • git remote remove <remote_repo_name>: remote repo와의 연결을 끊는다.

git push <remote_repo_name> <local_branch_name>

local branch의 commit을 연결된 remote branch에 반영한다.

  • 최초에는 --set-upstream 으로 local branch와 remote branch를 연결해야 한다.
    그래야 서로 tracking이 되어, 이후 push나 pull하기 용이하다.
  • 다른 사람이 먼저 push를 했다면, pull을 먼저 한 다음에 push할 수 있다.
    (이럴 땐, pull대신 fetch를 사용하여 conflict가 발생하는지 미리 확인할 수 있다.)

git pull <remote_repo_name> <remote_branch_name>

remote branch의 commit을 local branch로 가져와 반영한다.
이 때, local branch는 자동으로 remote branch와 merge를 시도한다.

  • 자동으로 merge하지 않고 remote branch의 내용만 가져오려면 fetch를 사용한다.
    이후, 수동으로 remote branch와 merge를 해줘야 한다. (fast forward)

git clone <remote_repo_path> .

remote repo를 현재 위치한 directory인 local로 복제하는 것이다.

  • ‘.’을 붙이지 않으면 현재 디렉터리에 clone한 directory가 따로 생성된다.
  • clone은 init; remote add; pull 을 한 것과 같다.
  • -b <branch_name> --single-branch: 특정 branch만 clone할 때 사용한다.

자주 쓰는 명령어


최근 local commit 이후로 한 작업 모두 취소

  • git reset --hard
  • git clean -fd (필요시)

최근 local commit 취소 (이 직전 커밋으로 돌아감)

  • git reset --hard HEAD~1
  • git clean -fd (필요시)

0개의 댓글