혼자 해보는 git

앞의 게시물에서 git의 기본적인 시작법을 배웠다면, 이제부터는 본격적인 개발을 위한 git을 배워봅니다.

프로젝트 구성

앞서 $ git clone을 이용하여 remote repository를 생성할 때, 세개의 파일을 생성했습니다. 각 파일에 대해 알아보자면,

README.md

README.md는 이 repository 또는 Project를 설명하기 위한 표지와 같습니다. 이 Project에 대한 간략한 소개와 함께 설치법, 라이센스, 구성 등을 설명합니다.

.md 는 Markdown으로 웹문서를 작성할 때 사용하는 HTML을 좀 더 편리하게 작성할 수 있도록 각 태그를 1:1 매칭한 문법이 존재합니다.

다만 표준이 존재하지 않기 때문에 github flavored Markdown 문법으로 작성하셔야 의도한 대로 보이게 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!-- 주석표기 -->

<!-- 제목 텍스트 -->
# h1
## h2
### h3
#### h4
##### h5
###### h6

<!-- 순서 없는 리스트(- * + 혼용 가능) -->
- Item1
- Item1-1
- Item1-1-1
* Item2
+ Item3

<!-- 순서 있는 리스트 -->
1. Item1
2. Item2

<!-- 하이퍼링크 -->
[링크 텍스트](링크 URL)

<!-- 이미지 -->
![대체 텍스트](이미지 URL)

<!-- 강조 표기 -->
*Italic*
**Bold**
~Line Break~
_Single underscore_

<!-- 인용문(Blockquote) -->
> 인용할 문장

<!-- Code 입력(문장 내) -->
This is how `code` works.

<!-- Code 입력(블록) -->

` ``` `
def say_hello():
return "hello"
` ``` `

<!-- 수평선 -->

Page 1

***
Page 2

-----
Page 3



LICENSE

오픈소스 프로젝트에서 가장 중요한 License는 내가 만들 때에도, 배포할 때에도 가장 신경써야 하는 일 중 하나입니다.

가장 많이 사용하는 License는 다음과 같습니다.

  • MIT License
    • MIT에서 만든 라이센스로, 모든 행동에 제약이 없으며, 저작권자는 소프트웨어와 관련한 책임에서 자유롭습니다.
  • Apache License 2.0
    • Apache 재단이 만든 라이센스로, 특허권 관련 내용이 포함되어 있습니다.
  • GNU General Public License v3.0
    • 가장 많이 알려져있으며, 의무사항(해당 라이센스가 적용된 소스코드 사용시 GPL을 따라야 함)이 존재합니다.

.gitignore

.gitignore는 git이 파일을 추적할 때, 어떤 파일이나 폴더 등을 추적하지 않도록 명시하기 위해 작성하며, 해당 문서에 작성된 리스트는 수정사항이 발생해도 git이 무시하게 됩니다.

특정 파일 확장자를 무시하거나 이름에 패턴이 존재하는 경우, 또는 특정 디렉토리 아래의 모든 파일을 무시할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
# 주석을 달기 위한 Hashtag

# MacOS Setup
.DS_Store

# Python cache files
.py[cdo]

# Important files
/Important

# AWS key
key.pem

Troubleshoot: 각 단계별 되돌리기, 수정하기

작업을 하다보면 실수로 어떤 일을 했을 경우, git에서는 다음과 같은 방법으로 되돌리거나 삭제할 수 있습니다.

Rename files, directories

파일이나 폴더를 이동하거나 이름을 바꿀 경우, git은 rename이 아닌 deleted, untracked 로 기존의 파일이 삭제되고 새로운 파일이 생성되었다고 인식하게 됩니다.

이런 경우, 특정 파일에 대한 이력을 확인하기 힘들어 질 수 있기 때문에 반드시 이동 관련 명령들은 git에게 해당 작업을 위임처리 해야 합니다.

Worst: $ mv server.py backend/

Best: $ git mv server.py backend/

Undoing

작업을 열심히 하다가 잘못된 방향으로 들어서기 시작하면 깨닫는 순간 이미 늦었다는 사실을 알아차립니다. 이럴 때 선택할 수 있는 것은 (중간중간 저장했다면) 해당 commit으로 이동할 수 있겠지만, 만약 해당 branch의 최신사항으로 돌아가 다시 시작하고 싶다면 다음과 같이 명령합니다.

asciicast

전체 되돌리기

1
$ git checkout -- .

특정 파일만 되돌리기

1
$ git checkout -- 파일이름

Unstaging

작업사항을 $ git add 하였으나, 해당 commit이 아니라서 unstaging을 해야 하는 경우, Index에 올라간 파일을 내려주면 됩니다.

asciicast

1
$ git reset HEAD 파일이름

Remove with unstage

Unstaging과 동시에 파일 삭제까지 하고 싶을 때에는 $ git rm -f 파일이름 이라고 하면 파일을 unstaging 후 삭제까지 진행합니다.

Edit commit

Commit이 끝나 repository에 존재하는 commit을 수정하기 위해서는 다음과 같이 수행합니다.

직전 commit에 대해

Remote repository로 push 되지 않은 직전 commit을 수정하기 위해서는 --amend flag를 사용합니다.

  • 가장 최근 local commit 수정, 삭제하는 영상
    asciicast
1
$ git commit --amend

이전 commit에 대해

이미 직전 커밋이 아니게 되어버린 commit들은 rebase를 활용합니다.

1
$ git rebase -i <commit>

만약 rebase 동작 중 중지를 원한다면, --abort flag로 해당 작업을 중지합니다.

1
$ git rebase --abort
  • rebase 중지하기

asciicast

이전 commit 메시지 수정하기
  • rebase하여 commit 수정하기

asciicast

1
2
3
4
5
$ git rebase -i <commit>

$ git commit --amend

$ git rebase --continue

Reset commit

Local repository에 존재하는 commit을 삭제하는 것은 큰 문제가 되지 않습니다. 하지만 협업중에 누군가 이미 pull 해버린 파일을 지우는 것은 많은 수고가 들어가게 됩니다. 이 때 선택할 수 있는 두가지 옵션 중 각 옵션의 차이를 알아봅니다.

Worse Case: Reset

$ git reset 을 활용하면 이전 커밋을 삭제할 수 있습니다.

  • reset 으로 commit 삭제한 뒤 remote repository에 반영하기

asciicast

ex) 현재 HEAD에서 이전에 올라간 3개의 commit 삭제, 되돌린 이력으로 remote에 강제 push

1
2
3
$ git reset --hard HEAD~3

$ git push -f origin <branch>

이 명령을 수행하면 이 커밋들은 세상에 존재한 적이 없게되어 버려 깔끔해 보일 수 있지만 앞서 설명한 협업의 관점에서는 파일이 다시 살아난다던지, 과거의 이력이 사라지기 때문에 불완전한 이력이 되어버릴 수 있습니다. 혼자 할 때에도 이 방법을 추천하지 않는 이유가 내가 실수한 이력이 있더라도 그것을 고쳐내는 commit으로써 해당 이력을 유지해야 저장소의 연속성과 완전성을 보장 할 수 있습니다.

Better Case: Revert

방법은 같지만 명령어가 다릅니다.

기존의 실수한 이력을 거슬러 올라가면서 해당 사항을 최신으로 끌어올리는 revert를 사용합니다.

  • revert 로 commit 취소 이력 남기기

asciicast

ex) 현재 HEAD에서 직전의 3개의 commit을 순서대로 거슬러 올라가 해당 내역에 대해 commit, push 수행

1
2
3
4
5
$ git revert --no-commit HEAD~3..

$ git commit

$ git push origin <branch>

이렇게 함으로써 commit을 되돌린 이력으로 최신을 유지함과 동시에 되돌리고자 했던 작업들도 남길 수 있게 됩니다.
자주 수행하게 되면, 위의 reset에 비해 모든 commit이 순방향으로 진행되지 않기에 이해에 어려움을 느낄 수 있지만, 이 문제는 commit 제목의 말머리를 달아줌으로써 해결할 수 있고, 되돌리고자 한 이유와 내역을 모두 남길 수 있어 팀원간의 케이스 공유에서는 더욱 도움이 됩니다.

Practice

두개의 커밋을 생성한 뒤, 이 커밋을 취소하는 작업을 revert를 활용하여 진행해보세요.