다시 시작하는 Git, GitHub 기초 3
-
이 글은 충북대학교 SW중심사업단의 "Git/GitHub 기초/고급 특강" 강의를 바탕으로 작성되었습니다.
-
포스팅에 사용된 Git 연습 툴 : https://git-school.github.io/visualizing-git
-
썸네일 이미지 출처 : www.freecodecamp.org - https://www.freecodecamp.org/news/an-introduction-to-git-for-absolute-beginners-86fa1d32ff71/
2021년 3월 15일
이제 드디어 Git/GitHub 기초 특강의 마지막 부분입니다.😄 이번에는 리포지토리와 커밋의 구체적인 내용에 대해 작성하겠습니다.
리포지토리의 정체
지난 시간에 $ git clone
명령어로 원격 저장소를 그대로 가져오는 실습을 진행해보았는데요, clone
으로 만들어진 프로젝트 폴더와 저장소에서 소스 코드를 복사해와서 직접 만든 폴더는 어떻게 다를까요?🤷♂️
clone
으로 가져온 리포지토리 폴더는 직접 만든 폴더와 다르게 리포지토리의 정보가 들어있는 .git
이라는 숨김 폴더를 가지고 있습니다. $ git clone
으로 프로젝트를 복사해오면 .git
폴더도 함께 가져오게 되는데요, 덕분에 클론 받은 저장소에서도 커밋을 이어서 진행할 수 있습니다.
리포지토리 로컬 환경에 만들기💾
이번에는 새 리포지토리를 직접 만드는 과정을 진행해보겠습니다.
- 프로젝트명으로 디렉토리를 생성합니다.
- 프로젝트 디렉토리에서
$ git init
명령어를 실행합니다.
init
명령어를 입력했을 때 bash 창에 뜨는 디렉토리 뒤에 master라는 글자가 생겼다면 성공입니다!
이제 .git
폴더가 생겼는지 확인해봅시다. ls
명령어에 -a
옵션을 주면 숨김 파일까지 볼 수 있습니다. $ ls -a
명령어로 확인해보면 .git
폴더가 생성된 것이 보입니다.
또한 $ git status
명령어로 저장소의 상태를 볼 수 있습니다.
status
명령어 입력 후 보이는 정보는 다음과 같습니다.📋
On branch master
: 현재 master 브랜치에 있음.Changes not staged for commit
: 스테이징 영역에 추가하지 않은 변경 사항 있음.Untracked files
: 한 번도 커밋하지 않은 파일. 저장소에 반영되지 않은 파일.
스테이징 영역
Git에는 스테이징 영역이라는 개념이 존재합니다. 스테이징 영역은 간단히 말해서 파일을 저장소에 업데이트 하기 전에 업데이트 할 파일들을 모아놓는 중간 지점이라고 할 수 있습니다.
출처 : Git/GitHub 기초/고급 특강 PPT
이런 스테이징 영역을 사용하는 방법은
- 내가 원하는 파일만 스테이징 영역에 옮기고,
- 커밋을 통해 그 파일들만 저장소에 반영하면 됩니다.
이런 스테이징 영역은 왜 존재할까요? 저번 Git 포스팅에서 커밋은 논리적 단위로 구분되는 것이 좋다고 했는데요, 막상 버그를 수정하거나 새로운 기능을 구현하다 보면 프로젝트 내의 파일들을 이것저것 건드리는 일이 많습니다. 이럴 때 관련된 파일만 스테이징 영역으로 옮기고 커밋을 진행하면 실제 건드렸던 파일과는 상관없이 같은 논리적 변경 사항만 커밋할 수 있습니다.
스테이징 영역에 파일 추가
$ git add 파일명
명령어로 파일을 스테이징 영역에 추가할 수 있습니다.
$ git status
명령어로 확인해보면 Changes to be committed
라는 글자 밑에서 추가한 파일명을 볼 수 있습니다. 저는 test
폴더에서 file1.js
파일을 스테이징 영역에 추가했습니다.
bash창에도 나와있는 것처럼 $ git rm --cached 파일명
명령어로 스테이징 영역에서 파일을 다시 내릴 수도 있습니다.
$ git add .
명령어로 감지된 변경 사항이 있는 모든 파일을 스테이징 영역으로 옮길 수 있습니다. 하지만 의도치 않은 변경사항까지 커밋에 들어가거나 커밋 단위의 논리적 구분이 흐려질 수 있기 때문에 추천하는 방법은 아닙니다.
커밋 만들기
이번에는 스테이징 영역에 올라온 파일을 저장소로 커밋해보겠습니다.
$ git commit -m '커밋 메시지'
명령어로 커밋을 만들 수 있습니다. 이때 커밋 메시지 부분에 어떤 내용을 작성해야 하는지, 어떤 형식으로 작성해야 하는지는 첫 포스팅에 정리해놓았습니다.
커밋 후에 $ git status
명령어로 다시 확인해보면 스테이징 영역이 비어있는 것을 볼 수 있습니다.
잘못 만든 커밋 되돌리기⚙️
원래 이 파트를 <커밋 만들기>의 하위 항목으로 만들려고 했는데요, 양이 너무 많은 관계로 별도 항목으로 만들었습니다. 새로운 커밋을 만드는 것은 쉽지만 한 번 지나간 커밋을 되돌리는 작업은 쉽지 않습니다. 커밋을 만들 때보다 고려해야 할 사항이 많은데요, 크게 나눠서
- 원격 저장소 반영 여부와
- 커밋 이력 유지 여부에 따라 방법이 달라집니다.
로컬에서 되돌리기
일단 가장 기본적인 로컬에서 커밋을 되돌리는 방법부터 살펴보겠습니다.
reset - 커밋 이력 삭제
$ git reset 커밋 아이디
명령어로 해당 커밋 버전으로 되돌아갈 수 있습니다. 혹은 커밋 아이디
부분에 HEAD~돌아가고 싶은 커밋 수
를 입력하면 HEAD부터 해당 커밋까지 되돌아가게 됩니다. 예를 들어 현재 버전의 바로 전 커밋으로 돌아가고 싶다면 $ git reset HEAD~1
이라고 입력하면 됩니다.
reset
명령어는 돌아가는 길에 있는 모든 커밋 이력을 삭제합니다. 이제부터는 git 시각화 사이트를 이용해서 설명하겠습니다. git 명령어를 연습할 수 있는 유용한 사이트입니다.
사이트 : https://git-school.github.io/visualizing-git
여기 제 커밋 이력이 있습니다. 여기서 ff51e45
커밋으로 돌아가고 싶다면
$ git reset ff51e45
또는& git reset HEAD~2
명령어를 입력하면 됩니다.
보이는 것처럼 HEAD가 해당 커밋으로 되돌아갔습니다. 앞의 두 커밋은 이력에서 삭제됩니다.
그런데 되돌아간다는 말로 끝내기에는 Git의 구조가 복잡합니다.🤔 로컬 저장소, 스테이징 영역, 워킹 디렉토리 중에 어디부터 어디까지 reset
의 효과가 반영된다는 말일까요? Git은 reset
명령어의 옵션으로 반영 범위를 지정할 수 있게 해줬습니다.
soft
$ git reset --soft 커밋 아이디
명령어는 로컬 저장소에서만 커밋을 되돌립니다. 즉, commit
명령어를 입력하기 바로 전 단계로 되돌아간다고 할 수 있습니다. 스테이징 영역과 워킹 디렉토리 상에는 여전히 리셋하기 전의 파일이 남아있습니다.
mixed
$ git reset 커밋 아이디
명령어는 사실 --mixed
옵션이 디폴트로 설정되어 있습니다. 이 명령어는 로컬 저장소와 스테이징 영역에만 영향을 미칩니다. 즉, add
명령어를 실행하기 전 단계로 되돌아간다고 할 수 있습니다. 현재 프로젝트 폴더 내의 파일에는 변화가 없지만 두 영역의 파일은 해당 커밋 버전으로 되돌아갑니다.
hard
$ git reset --hard 커밋 아이디
명령어는 가장 조심해서 다루어야 합니다. 이름에서 유추할 수 있듯이, --hard
옵션은 모든 영역에 영향을 미칩니다. 만약 워킹 디렉토리 상의 변경 사항을 저장하지 않았다면 변경 사항을 잃어버리게 됩니다.
revert - 커밋 이력 유지
$ git revert 커밋 아이디
혹은 $ git revert HEAD~
명령어로 해당 커밋 버전과 정확히 반대되는 커밋을 새로 만들 수 있습니다. 이 revert
를 단순히 해당 커밋 버전으로 돌아간다고 잘못 이해하는 경우가 많은데요, 간단한 예시를 통해 알아보겠습니다.
텍스트 파일을 새로 만들고 다음과 같이 작성하고 커밋합니다.
1. Hello World
그리고 두 번째 줄을 추가하고 다시 커밋합니다.
1. Hello World
2. Hello Hello World
여기까지의 과정을 시각화하면 다음과 같이 보입니다. 파일을 만들고 첫 번째 줄을 만든 것이 first commit
이고 현재 버전이 두 번째 줄을 추가한 두 번째 커밋입니다.
여기서 두 번째 줄을 추가한 커밋이 만약 잘못된 커밋이라면 $ git revert HEAD
명령어를 통해 직전 커밋을 되돌리는 커밋을 생성할 수 있습니다.
이런 식으로 해당 커밋과 반대되는 새로운 커밋이 생성됩니다. revert
이후 파일의 상태는
1. Hello World
과 같이 첫 번째 커밋 버전으로 돌아가 있을 것입니다. revert
로 만든 커밋이 두 번째 줄을 삭제하는 역할을 했기 때문입니다.
만약 파일 생성 자체를 없었던 일로 하고 싶다면 단순히 $ git revert HEAD~1
명령어를 사용해서 첫 번째 커밋을 되돌리면 될까요? 이렇게 revert
를 사용하면 충돌이 발생합니다. 첫 번째 커밋을 되돌려야 하는데 그 이후에 생긴 두 번째 커밋의 변경 사항을 어떻게 처리해야 할 지 Git이 알 수 없기 때문입니다. 따라서 revert
는 최신 커밋부터 하나하나 거치며 신중하게 진행해야 합니다.
원격 저장소 커밋 되돌리기
이번에는 원격 저장소까지 올라가버린 커밋을 되돌리는 방법에 대해 알아보겠습니다. 다음 강의의 예습이라고도 할 수 있는데요, 미래에 같은 문제로 고민할 자신을 위해 커밋 되돌리는 방법을 한 번에 요약해놓으려고 합니다.
reset - 강제 push
앞서 reset
으로 커밋을 되돌리는 방법이 목표 커밋 이후에 만들어진 커밋들을 삭제한다고 했습니다. 이 말은 로컬 저장소의 커밋 버전이 원격 저장소의 커밋 버전보다 낮아진다는 것을 뜻하므로 해당 변경 사항을 원격 저장소에 반영하기 위해서는 강제로 push
하는 작업이 필요합니다.
세 개의 커밋을 만들고 모두 원격 저장소에 push
로 반영한 모습입니다. 여기서 바로 전 커밋으로 reset
작업을 진행하겠습니다.
보이는 것처럼 원격 저장소의 커밋 버전은 최신이지만, 로컬 저장소의 커밋 버전은 한 단계 낮아진 것을 볼 수 있습니다. 이 상태에서 push
를 하게되면 당연히 거부되는데요, 원격 저장소의 커밋보다 낮은 단계의 커밋을 이어서 붙일 수는 없기 때문입니다.
따라서 $ git push -f origin master
명령어를 통해 강제로 push
를 진행해야 합니다.
강제로 push
를 진행하면 원격 저장소의 커밋도 사라지게 됩니다. 이 방법은 협업 시 충돌이 발생할 수 있는 매우 위험한 방법으로 사전 협의 없이 독단적으로 사용해서는 안 됩니다.
revert - 커밋 이력 유지
revert
명령어는 해당 커밋 버전과 반대 역할을 하는 새로운 커밋을 만든다고 했습니다. 따라서 원격 저장소에 해당 변경 사항을 반영하고 싶다면, push
를 해주기만 하면 됩니다. 그러면 새 커밋으로 원격 저장소에 추가됩니다.
이것으로 Git/GitHub 특강 기초편을 모두 마쳤습니다. 다음 포스팅부터는 고급편을 이어서 적겠습니다.
<참고 문서>
Author And Source
이 문제에 관하여(다시 시작하는 Git, GitHub 기초 3), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@soonitoon/다시-시작하는-Git-GitHub저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)