저번 시간에 우리는 작업에 대한 이력을 내 컴퓨터에 남길 수 있는 commit 하기를 알아봤습니다.

우리가 commit 하는 이유는 뭘까요? 작업 이력을 남겨두고, 원하는 시점으로 자유롭게 돌아다니기 위해서라고 할 수 있죠.

이번에는 저장한 commit 간 이동하는 방법에 대해 알아보려 합니다.

그리고 외부 저장소에 push/pull 해보는 것까지 다뤄보도록 하죠!


Git history 관리 방법

저번에 git log 를 통해 본 커밋 이력에서, HEAD 란 문자를 본 적이 있으실 겁니다.

HEAD 는 현재 내가 위치해있는 커밋을 가리키는 식별자 입니다. 보통 가장 최신의 커밋을 가리키고 있죠.

커밋과 커밋을 이동할때는 git reset 을 사용해줍니다.

1. 커밋 간 이동하기 

git reset --{option} {commit_id} 입력

예시로, git reset --hard 8564 를 입력해주면, 워킹 디렉토리의 모습이 HEAD 가 가리키는 commit 의 모습으로 변하는 것을 확인할 수 있습니다.

git reset 명령어를 이용해, 우리는 언제든지 원하는 커밋으로 돌아갈 수 있는 것입니다.

명령어 중 --hard 의 부분은 옵션인데요, 옵션에 따라 working directory, Staging Area, Repository의 지정 커밋이 바뀝니다. 가령 위의 예시에서 워킹 디렉토리가 함께 바뀌는 이유는 hard 를 옵션으로 설정해주었기 때문입니다.

조금 헷갈리시나요? 옵션 별 차이를 간단하게 정리해보겠습니다.

2. 옵션 별 차이 

이미지 출처 : 한국정보산업연합회

- 공통 : Repository 에서 Head 가 특정 commit을 가르킴.

- Hard : Staging Area 와 워킹 디렉토리가 특정 commit 으로 바뀜.

- Mixed : Staging Area 가 특정 commit 으로 바뀌나, 워킹 디렉토리는 바뀌지 않음 (가장 최근 커밋으로 유지)

- Soft : Staging Area와 워킹 디렉토리가 바뀌지 않음 (가장 최근 commit 으로 유지)

 

그렇다면 soft, mixed 옵션은 언제 사용하면 유용할까요?

예를 들어, 팀원A가 커밋1~6 을 만들었습니다. 그리고 지금은 워킹 디렉토리에서 커밋 6 에 대해 많은 작업을 했습니다.

작업을 하고나니 커밋 1~3은 괜찮지만, 4~6 은 너무 조금씩만 고쳐서 굳이 업로드 하지 않아도 될 것 같습니다.

이런 경우에, mixed/soft 옵션을 사용해서, 현재 작업한 워킹 디렉토리의 내용을 남기고 커밋3으로 이동합니다.

이 상태에서 커밋을 새로 하게 되면, HEAD 가 가리키는 커밋3 위에 새로운 커밋6이 쌓이기 때문에 불필요한 커밋을 없애고 필요한 커밋만을 보여주는 것이 가능합니다.

위의 그림을 보면, mixed/soft 옵션을 사용해 HEAD 만을 변경하고 커밋해 커밋7을 올리는 과정을 알 수 있지요.

git reset 의 옵션 중, hard 옵션을 사용할때는 특히 주의해야 합니다.

hard 옵션은 워킹 디렉토리를 다른 커밋의 버전으로 바꿔주기 때문에, 자칫하면 워킹 디렉토리에서 새롭게 작업하던 내용이 다 날라갈 수 있기 때문입니다.

 

3. 추가적인 명령어

- git status 

git status 는 파일 상태를 알아볼 수 있는 명령어 입니다. 아래의 코드를 볼까요?

캡쳐에 포함되지 않아서 보이지 않지만, 제 디렉토리의 커밋1(이름 : 8564) 에는 BasicCar1 파일이 있고, 커밋2(이름 : aa08) 에는 현재 BasicCar1 파일과 BasicCar2파일이 있습니다.

코드를 보면 가장 처음에 hard 옵션을 이용해 커밋2의 워킹 디렉토리와 스테이징 공간을 불러왔습니다. 그리고 mixed 옵션을 이용해 커밋2의 워킹 디렉토리를 그대로 둔 채 커밋1의 스테이징 공간만을 불러왔죠. 이 때, git status를 입력해 파일의 상태를 알아보면, 빨간색으로 BasicCar2.js 파일의 이름이 나타나며, 커밋되지는 않았지만 워킹디렉토리에 있다. 커밋할거면 get add 명령어로 커밋해라고 말해줍니다. 즉, 워킹디렉토리에는 이 파일이 있는데 스테이징 공간에 없다는 것입니다. 당연하겠죠? 왜냐면 커밋1의 스테이징 공간에는 BasicCar2.js 파일이 없으니까요! 

다음으로 다시 hard 옵션을 사용해 커밋2의 워킹 디렉토리와 스테이징 공간을 불러옵니다. 그 후 soft 옵션을 이용해 다른것을 그대로 둔 채 HEAD 가 커밋1을 가리키도록 하였죠. 이 때 git status 를 입력해 파일의 상태를 알아보면, 초록색으로 BasicCar2.js 파일의 이름이 나타납니다. 워킹 디렉토리에도 있고, 스테이징 아리아에도 있으니 이렇게 나타나는 거지요.

이제 각 옵션들의 차이, 그리고 git status 의 기능이 조금 이해가 되시나요?

 

- git reflog

일전에 알아본 git log 는 사실, HEAD 가 가리키는 커밋을 기준으로 그 이전에 커밋한 이력만을 보여줍니다.

그러면 문제가 있죠. 만약 내 디렉토리에 커밋1, 2, 3 이 있는데, git reset 명령어를 이용해 커밋1 로 갔습니다. 그리고 이제 커밋3으로 다시 돌아가고 싶어요. 그러면 커밋3의 이름을 어떻게 알죠? git log 명령어를 이용해도, 지금 나는 커밋1을 보고있기 때문에 커밋3의 이름을 확인할 수 없습니다.

이 때 사용할 수 있는게 바로 git reflog (reference log) 입니다. get reflog 는 이때까지 HEAD 가 가리켰던 commit 들을 순서대로 보여줍니다. HEAD@{n}  의 숫자가 작을수록 최근의 기록입니다. 각 커밋의 이름 대신에 head@{n} 을 사용해 지정할 수 있습니다.

 


지금까지는 Git 으로 버전 관리를 하며, 내 컴퓨터에만 저장을 했죠. 하지만 협업을 위해서, 그리고 프로젝트의 복구를 위해서 외부의 저장소에 우리의 파일을 업로드 할 필요가 있습니다.

외부 저장 서비스는 Github, GitLab, Bitbucket 등 다양하고, 서비스마다 각각의 특성과 장단점이 있지만 하나만 능숙히 사용할 수 있으면 다른 것들도 쉽게 사용이 가능합니다. 저희는 Gitlab 을 위주로 다뤄보겠습니다.

외부 저장소로 Push하기

1. 외부 저장소와 연결

git remote add origin {프로젝트의 gitlab url} 입력

git remote 명령어는 내 컴퓨터에서 내 컴퓨터에서 외부 저장소에 관한 작업을 할 때 사용하는 명령어입니다. 뒤에 다양한 종류의 명령어를 추가로 붙여서 다양한 명령을 수행 가능 합니다. 코드의 의미는 " url 이 가리키는 외부 서버의 프로젝트를 원격 저장소로 추가하는데, 이름을 origin 으로 하겠다."는 것입니다. (매번 긴 url을 쓸 수 없으니, origin 이라는 이름을 등록해주는 것.)

2. 디렉토리 내용 업로드

git push -u origin master 입력

git push 명령어는 "현재 내 프로젝트 디렉토리의 내용(.git 디렉토리 내부에서 관리되던 Repository 영역을 업데이트 한 것) 을 전부 origin 에 업로드 해라." 라는 것입니다. (-u , master 는 브런치 관련 내용으로, 추후 다뤄보겠습니다)

입력하면 아이디와 패스워드를 등록하라는게 나오는데, 프로젝트가 등록되어있는 자신의 gitlab 의 계정을 등록해주면 됩니다. url 만 입력해서 수정할 수 있었다면 url을 아는 팀원이 아닌 다른 사람이 함부로 수정할 수 있으니 꼭 필요한 부분이겠죠.

이렇게 외부 저장소와 연결하고, push 해준 후 gitlab 페이지에 가서 확인해보면, 지금까지 내가 한 commit 들이 시간순으로 다 보이는 것을 확인할 수 있습니다.

그리고, 처음에 이렇게 한번 push 를 해주면, 이후 명령시 디렉토리가 처음부터 origin 의 해당 프로젝트를 바라보고 있기 때문에 git push 만 입력해주면 됩니다.

.

 

외부 저장소에서 Pull 하기

그렇다면 반대로 Gitlab의 프로젝트에서 새로운 커밋이 Push 됐을 때 내 컴퓨터로 가져오려면 어떻게 해야할까요? 

혹은 새롭게 팀에 합류하게 되어 기존에 팀이 만들던 프로젝트를 가져오려면 어떻게 해야 할까요?

 

1. 처음 가져올 때

git clone {가져올 프로젝트의 url} 입력

이 명령어를 입력해주면, 페이지에 올라가 있던 커밋들을 하나의 디렉토리 형태로 그대로 복사해 가져옵니다.

주의할점은 우리가 clone 한 프로젝트 폴더는 지금 있는 폴더가 아니라 가져온 폴더이기 때문에,

리눅스 명령어 cd 를 이용해 clone 한 프로젝트 디렉토리로 이동한 뒤 git 명령어를 실행해야 한다는 점입니다. 

앞서 잠깐 언급한 적이 있었죠?

이후, #1 문서에서 다뤘던

git config user.name , git add , git commit -m "{commit설명} 을 써주고

git push 를 이용해 push 해주면 됩니다.^^ 

( 이때는 원격 저장소에 있던 프로젝트를 clone 한 것이기 때문에 별도로 git remote 를 쓰지 않아도 됩니다.)

 

2. 새로운 커밋을 가져올 때

 git pull 입력

이 간단한 명령어를 통해 현재 디렉토리가 바라보고 있는 gitlab 서버의 최신 커밋을 가져올 수 있습니다.

쉽게 버전을 관리하며 협업이 가능하겠죠?

 

포인트

1. 이름으로 origin 을 사용하자

git을 사용할 때, 관습적으로 외부 프로젝트 저장소의 이름을 origin 으로 합니다. 앞서 봤던 git remote add origin {url} 에서 봤듯이 말이에요. 그리고, 보통 여러 개발자가 함께 개발할때 새롭게 참여한 팀원은 다른 팀원에게 소스코드를 넘겨받는것이 아니라, git clone {url} 을 통해 가져옵니다. 내부 저장소에서 가져오는 것이 항상 가장 최신의 커밋을 가져온다는 보장을 하기 때문이죠. 이처럼 항상 기준이 되고, 근원이 되는 것은 gitlab에 있는 파일이기 때문에 origin 이라는 이름을 붙입니다.

2. Push 이전에 Pull 이 있다.

새로운 작업의 시작 전에는, 항상 내 컴퓨터에 있는 프로젝트가 gitlab 서버에 있는 최신 프로젝트를 포함하는지 확인하고 작업해야 합니다. 예를 들어 gitlab 의 최신 프로젝트에는 commit1, 2, 3, 4 가 있는데 내 컴퓨터에 commit 1, 2, 3 이 있어서, 이를 작업해 commit 1, 2, 3, 5 를 만들어 Push 하면 안되겠죠. 이렇게 되면 commit 끼리 충돌하며 Fail 할 수도 있습니다. 내 프로젝트로 gitlab 의 프로젝트를 덮어 씌우는 것은 보통 허용되지 않습니다. 포인트는 새 작업을 하기 전에는 무조건 git pull 로 최신 버전을 가져오자는 것입니다. Push 이전에는 Pull 이 있습니다.


오늘로 Git 과 Gitlab 에 대한 기본적인 내용이 마무리된 것 같습니다..

다음 글에서는 중요한 주제인 Git branch 만드는 법, Merge하는 법, Comflict해결 등을 알아보도록 하겠습니다. 

총총..

 

 

 

 

 

 

 

 

+ Recent posts