이번주에 스터디에서 유용한 Git의 명령어들에 대해 발표를 하게 되었는데 정말 좋은 기능들이 있어 많은 사람들과 공유하고 싶어 글을 쓰게 되었습니다.

Content


이 포스트의 내용은 Pro git 책의 Chapter 7 Git Tools 내용의 일부입니다. 혹시 더 자세한 내용을 원하신다면 링크를 들어가 보시는 것을 추천드립니다.

Git 이란?


깃(Git)은 컴퓨터 파일의 변경 사항을 추적하고 여러 명의 사용자들 간에 해당 파일들의 작업을 조율하기 위한 분산 버전 관리 시스템 입니다. 특징으로는 파일의 변경 사항을 스냅샷 단위로 SHA-1 해쉬 값을 붙여 관리하며, 이 SHA-1 값이 중복 되거나 손실되지 않는 한 지속적으로 파일을 추적할 수 있습니다.

커밋 조회하기


깃은 커밋을 조회하기 위한 다양한 CLI 명령어들을 가지고 있습니다.

  • git log
  • git show
  • Double Dot
  • Triple Dot

git log

git log는 커밋 히스토리를 조회할 때 많이 사용하는 명령어 입니다. CLI로 git을 사용할때 굉장히 자주 사용하는 명령어 중 하나인데 히스토리를 유용한 옵션이 있습니다.

  • -p or --patch

이 옵션은 각 커밋에 대해 diff 결과를 보여줍니다. log 명령은 커밋 히스토리를 최신 커밋을 기준으로 내림차순으로 보여주기 때문에 짧은 커밋 기록만 보고 싶다고 하시면 -번호 옵션을 같이 주시면 보여지는 커밋의 갯수를 조절할 수 있습니다.

$git log -p -2
---
commit ef4b4c30e7dc3c25443ebb11b0ed5c83e5e8e730 (HEAD -> master, origin/master)
Author: Jane Lee <Yesdoing13@gmail.com>
Date:   Sun Jun 16 23:32:39 2019 +0900

    add Readme.md

diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..00c59f9
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,2 @@
+# 내맘대로 React A to Z
+

commit b9a48855d1d6ff2e1f3933041f7b900dd95cf268
Author: Jane Lee <Yesdoing13@gmail.com>
Date:   Sun Jun 16 23:31:09 2019 +0900

    first commit

diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..456751f
  • -S

이 옵션은 코드에서 추가되거나 제거된 내용 중에 특정 텍스트가 포함되어 있는지를 검색합니다. 예를 들어 어떤 함수가 추가되거나 제거된 커밋만을 찾아보려면 아래와 같은 명령을 사용하시면 됩니다.

$ git log -S function_name


git show

$ git show 명령은 깃 내부에 존재하는 여러 객체들을 조회할 때 사용되는 명령어 입니다. SHA-1 hash 값, tag 명, branch 명 등등 여러가지 객체들을 조회할 때 사용되는 명령 입니다.

  • @{n} 규칙

@{n} 규칙은 n 안에 넣을 수 있는 여러가지 조건이 있습니다. 대표적으로는 숫자와 시간이 있는데 숫자를 넣을 경우 그 숫자만큼의 커밋들을 보여주고 시간을 넣을 경우 현재부터 지정한 시간까지 한 커밋들을 볼 수 있습니다.

$ git show master@{yesterday}
---
commit 38b565a57e66b912b1b60ccb2695381f9d5aa77f (HEAD -> master, origin/master, origin/HEAD)
Author: Jane Lee <Yesdoing13@gmail.com>
Date:   Sat Jul 13 19:45:48 2019 +0900

    add kata solution

diff --git a/5kyu-EsolangInterpreters2.js b/5kyu-EsolangInterpreters2.js
new file mode 100644
index 0000000..e90d4d6
--- /dev/null
+++ b/5kyu-EsolangInterpreters2.js
@@ -0,0 +1,66 @@
+/*
+Desciption:
+Here are a list of commands in Smallfuck:
+
+> - Move pointer to the right (by 1 cell)
+< - Move pointer to the left (by 1 cell)
+* - Flip the bit at the current cell
+[ - Jump past matching ] if value at current cell is 0
+] - Jump back to matching [ (if value at current cell is nonzero)
+As opposed to Brainfuck where a program terminates only when all of the commands in the program have been considered (left to right),

Double Dot

Double Dot은 범위를 표현하는 문법으로 .. 을 사용해 여러 커밋을 한꺼번에 조회할 때 사용하는 명령어 입니다. 이 기능을 사용하면 브랜치를 유용하게 관리할 수 있습니다. 예를 들면, 주 브랜치에 Merge가 안된 브랜치 들을 검색할 수 있습니다.

위 그림과 같은 Git 예제가 있을 때 experiment 브랜치의 커밋들 중에서 아직 master 브랜치에 Merge하지 않은 것들을 보고 싶다고 할 때 다음과 같이 명령을 사용 할 수 있습니다.

$ git log master..experiment
---
D
C

반대로 experiment 에는 없고 master 에만 있는 커밋을 보고 싶으면 순서를 거꾸로 하시면 됩니다. $ git log experiment..master

만약 3개 이상의 브랜치들을 검색하고 싶으시다면 ^ 이나 --not 옵션 뒤에 브랜치 이름을 넣으면 그 브랜치에 없는 커밋을 보여줍니다.

$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA 
$ git log refA refB ^refC // A와 B에는 있고 C브랜치에는 없는 커밋
$ git log refA refB --not refC 

Triple Dot

Triple Dot 명령어는 양쪽에 있는 두 브랜치들 사이에서 공통으로 가지는 것을 제외하고 서로 다른 커밋만 보여줍니다.

$ git log --left-right master..experiment
< F
< E
> D
> C

대화형 명령


깃에는 몇가지 명령어에 대해 대화형 명령을 적용할 수 있는 옵션이 있습니다.

-i 또는 --interaction 이라는 옵션을 주면 깃은 대화형 모드로 들어갑니다.

$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 src
  2:    unchanged        +1/-1 index.html

*** Commands ***
  1: status     2: update      3: revert     4: add untracked
  5: patch      6: diff        7: quit       8: help
What now>

이 옵션은 해당 명령어가 어떤 옵션들을 가지고 있는지를 보여줍니다. 위의 add 명령을 예로 들어 보겠습니다.

  • status: staging area에 추가할 파일들을 보여줍니다.
  • update: staging area에 추가할 파일들을 선택합니다.
  • revert: update 명령에서 추가한 파일 중 취소할 파일을 선택합니다.
  • add untracked: update 명령에서 추가할 수 있는 파일은 tracked한 파일, 즉 기존의 추적 중인 파일들만 추가할 수 있습니다. 이 명령을 이용하면 추적 중이지 않은 파일들을 staging area에 추가할 수 있습니다.
  • patch: 이 명령을 사용하면 "한 파일에서 일 부분만 staging area에 올릴 수 있습니다." git을 사용하여 커밋을 할 때 주로 듣는 말은 1커밋은 1개의 의미있는 기능을 가져야 한다고 하는데요. 개발을 할 때 이처럼 한 기능을 개발하고 바로 커밋을 하지 못했을 때 이 기능을 사용하면 일부분만 따로 staging area에 올려 커밋을 할 수 있습니다.
  • diff: staging area에 올릴 파일들에 변경 사항을 보여줍니다.
  • quit: 대화형 명령 상태를 종료합니다.
  • help: 이 명령들이 어떤 기능들을 가지고 있는지 알려줍니다.

위의 예시는 add 명령에 대해서만 예를 들었지만 git의 다른 명령들에도 대화형 명령을 실행할 수 있습니다. CLI를 사용할 때 모든 옵션들을 외우기 힘들었는데 저는 이 명령을 통해 여러가지 깃이 제공해주는 기능들을 잘 사용하고 있습니다.

Stashing과 Cleaning


Stashing 과 Cleaning을 깃이 추적하고 있는 파일들에 대해 적용할 수 있는 명령들입니다.

Stash


Stash 명령은 아직 커밋하지 않은 내용들을 두고 다른 브랜치나 우선 순위 개발을 진행해야 할 때 사용할 수 있는 아주 유용한 기능입니다.

$ git status
---
현재 브랜치 master
커밋할 변경 사항:
  (스테이지 해제하려면 "git reset HEAD <파일>..."을 사용하십시오)

    수정함:        1.txt

커밋하도록 정하지 않은 변경 사항:
  (무엇을 커밋할지 바꾸려면 "git add <파일>..."을 사용하십시오)
  (작업 폴더의 변경 사항을 버리려면 "git checkout -- <파일>..."을 사용하십시오)

    수정함:        2.txt

위의 status의 상태를 보면 1.txt 파일은 staging area 상태에 있고 2.txt는 아직 staging area 상태에 있지 않은 변경사항을 지닌 파일입니다.

이 경우에 브랜치를 이동할려고 하면 다음과 같은 오류가 발생합니다.

$ git checkout R2
---
error: 다음 파일의 로컬 변경 사항을 체크아웃 때문에 덮어 쓰게 됩니다:
    2.txt
브랜치를 전환하기 전에 변경 사항을 커밋하거나 스태시하십시오.
중지함

이럴 경우 git stash 명령을 사용하게 되면 이 변경 사항들이 깃의 임시 저장소에 저장됩니다.

저장된 변경 사항들은 git stash list 명령을 통해 확인할 수 있습니다 .

$ git stash list
---
stash@{0}: WIP on master: 35cd687 uuuu
stash@{1}: WIP on master: 35cd687 uuuu
stash@{2}: WIP on master: a984192 2 commit

저장된 변경 사항들은 스택으로 저장이 되며 최신 저장된 사항이 0번이고 나중에 저장된 사항이 2번입니다.

이 저장된 변경 사항을 다시 가지고 올때는 다음과 같은 명령어 들을 사용할 수 있습니다.

  • git stash pop : 스택에 쌓인 내용을 가져올 때 저장된 변경 사항을 현재 브랜치에 적용하고 기존의 stack에 있던 기록을 삭제합니다.
  • git stash apply : 스택에 쌓인 내용을 가져올 때 저장된 변경 사항을 현재 브랜치에 적용하고 기존의 stack에 있던 기록은 그대로 유지합니다. 이 유지된 기록은 git stash drop 명령을 통해 삭제할 수 있습니다.
  • git stash branch <브랜치 명> : stash 이후 변경된 내용이 많을 때 기존에 저장된 내용을 현재 브랜치에 불러오면 충돌이 발생할 수 있습니다. 이럴 때 이 명령어를 사용하면 stash된 커밋을 기준으로 새 브랜치를 만들어서 저장된 내용을 적용해 줍니다. 이후 이 브랜치와 현재 작업 중인 브랜치를 merge 시켜 충돌을 해결하면 현재 브랜치 상태를 더럽히지 않고 문제를 해결할 수 있습니다.

Cleaning


Stashing은 작업하고 있던 파일들을 저장하는 명령이라면 이 기능은 저장하지 않고 불필요한 파일들을 삭제하는 기능입니다. 이 명령은 신중하게 사용 해야합니다. 왜냐하면 Working Directory 안의 추적하고 있지 않은 모든 파일이 지워지고 복구 할 수 없기 때문입니다. 만약 저장해야할 사항이 있으면 git stash 명령을 사용해야합니다.

-n 옵션을 사용하면 지워질 파일들을 가상으로 실행해보고 어떤 파일이 삭제될지 알려줍니다. git clean 명령은 추적 중이지 않은 파일만 지우며, .gitignore

에 명시해서 무시되는 파일들은 지우지 않습니다.

항상 이 명령을 실행하기전에는 -n 명령을 사용해서 어떤 파일을 삭제할지 확인하고 지우거나 -i 를 통한 대화형 명령으로 차근차근 삭제해야합니다.