내 시간을 절약하는 git 명령어들

깃의 명령어를 소개하는 글이 아닌, 개인적으로 자주 쓰지만 자꾸 잊어버리는 명령어만 모아두는 글이다. 전체 명령어를 훑어보고 싶다면 깃의 공식 도서를 참고하자.

특정 텍스트가 포함된 commit 검색

>git log -S<텍스트>

특정 텍스트가 추가되거나, 삭제된 commit을 검색해 준다.

머지

>git merge --no-ff -Xtheirs <브랜치 이름>

merge 시, FF가 가능하더라도 merge commit을명시적으로 만든다. merge 할때, 타겟 브랜치의 파일에 우선순위를 준다.

머지 커밋 검색

>git log --merges

머지 commit만 골라서 찾아준다. 반대로 ‘–no-merges’ 옵션을 사용하면 순수 커밋을 찾을 수도 있다.

명령창에서 그래프 보기

>git log --pretty=oneline --graph

그래프는 GUI 툴에서 봐야 편하다. 평소에는 거들떠 보지 않던 gitk도 명령창 그래프보다는 낫다. 하지만, 간혹 써야할 때가 있으니..

추적하는 파일 목록  보기

>git ls-files

다른 분들에게 설명할 때 많이 쓰게된다.

저장된 git object 정보 보기

>git cat-file (-t|-p) <object>

‘-t’, ‘-p’ 파라미터를 오가며, 오브젝트들을 들여다보면 재미있다.

참고

회사에서 깃(Git)을 쓰고 싶어요

 

인터넷에는 깃(Git)의 장점에 대한 많은 글이 있다. 먼저 많이 회자되는 장점들을 무작위로 열거 해보자.

  • 미친듯이 속도가 빠르다.
  • 오프라인 작업이 가능하다.
  • 저장공간을 적게 차지한다.
  • 실수를 쉽게 복구할 수 있다.
  • 항상 대안이 있어 염려할 필요가 없다.
  • 커밋이 쉽다.
  • 커밋의 관리가 쉽다.
  • 특정 파일을 무시할 수 있다.
  • 브랜치를 만들 수 있다.
  • 내 상태를 확인할 수 있다.
  • 브랜치에서 체리픽(cherry pick)할 수 있다.
  • 커밋을 검색 할 수 있다.
  • 업무 흐름에 따라 관리할 수 있다.
  • 실험을 쉽게할 수 있다.
  • 과제 크기에 따라 다양한 커밋 전략을 세울 수 있다.
  • 협업이 쉽다.

깃 너무 좋다. 인터넷을 둘러봐도 칭찬 일색이다. 간혹 깃의 장점을 문의하는 질문이 보이면 , 깃 추종자들 수많은 장점과 함께 입에 침이 마르도록 칭찬하며 곧 질문한 이가 교화 되는 것으로 마무리 된다. 깃이 그렇게 좋다니 회사에서 안쓸 이유가 있을까? 쓰는게 좋겠다. 기획, 마케팅, 과제 관리자, 디자이너에게 달려가 당장 깃을 쓰자고 말하자.

그들을 설득할 수 있을지 망설여진다. 아마 못할 것 같다. 위에 열거된 장점을 모두 들이대도 어려울 것 같다. 그들은, 기존의 중앙관리식 형상관리도구(VCS)가 단순하거나, 한 곳에 저장하는게 보안이 쉽거나, 충분히 강력하다 말한다. 또, 굳이 새로운 도구를 옮기는데 학습 비용을 치룰 필요가 있냐거나, 깃이 너무 어렵다고 하기도 한다.

그들의 이유 또한 나를 설득하기엔 충분치 않지만, 마음은 이해가 된다. 내 생각에 그들에게는 장점이 없다(혹은 거의 없다). 위에 열거했던 많은 장점들은 하나로 귀결되는데, 개발자가 주도적으로 프로젝트를 운영할 수 있다는 것이다. 개발자가 원하는 원하는 곳에, 원하는 시간에, 원하는 것만 commit할 수 있다. 개발자에게만 유효하고 매력적인 부분이다. 그들의 용어로 현재라고 부르는 상태(최신, latest)에만 관심있는 그들에게는, 그저 이상하고 무서운데다 복잡한 무엇이고..

깃을 싫어하는 비 개발자는 이해하자.

그 밖에

개발자의 선택이라면 상관 없다.

하지만, 비개발자들의 반대에 부딪혀 깃 사용이 좌절된 회사라면 개발자 중심의 소프트웨어 회사는 아닐 것이다. 어쩌면,  소프트웨어 회사도 아닐지도 모르고..

참조

나의 Gerrit FAQ

게릿(Gerrit)은 문서화가 잘되어 있는 프로젝트다. 여기서는, 내게 필요한 내용만 골라 예제와 함께 모아둔다.

Code-Review와 Verified의 차이는 무엇인가?

Code-Review는 코드를 보고 주는 점수이고, Verified는 빌드에 이상이 없는 것을 확인하는 점수다. Verified는 젠킨스와 같은 CI 툴을 통해 자동으로 줄 수 있도록 하자.

왜 Gerrit의 계정을 사용하나?

깃은 계정 관리 기능이 없다. 그래서, 게릿을 통해 우회적으로 계정 관리를 지원한다.

review와 commit의 관계는?

게릿의 리뷰(Review)는 깃의 커밋 단위로 올라간다. 커밋을 모아 1개의 리뷰로 만들거나, 반대로 1개의 커밋을 쪼개 여러개의 리뷰로 올릴 수 없다.

그 밖에

  • 리뷰 요청 권한과 merge commit 리뷰 요청 권한은 분리되어 있다.
  • 리뷰에 점수 주기, 적용하기, abandon, rebase 등의 각 버튼 별 권한은 분리되어 있다.

참조

나의 깃 FAQ

깃은 이미 잘 설명된 글이 많으므로, 여기서는 내게 필요한 부분만 예제와 함께 모아 둔다.

commit에 변경사항이 빠진다?

git add는 커밋을 위해 스테이징 영역에 파일을 추가한다. 하지만, 추가할 때 파일 이름이 추가되는 것이 아니라, 현재까지의 변경사항이 추가되는 것이다. 그러므로, A 라는 파일을 git add 명령어로 스테이징 영역에 파일을 추가한 후 수정하면, 나중에 수정한 내용은 커밋에 포함되지 않는다.

git add와 git commit -a의 차이점

git add는 새로 만든 파일(untracked)이나 수정된 기존 파일을 스테이징 영역(Staging Area)에 추가한다. 이에 비해 git commit -a는 수정된 기존 파일만 추가하면서 커밋을 시도하기 때문에, 새로만든 파일은 누락할 수 있다.

깃의 cherry pick

스냅샷 기반으로 파일을 저장하는 깃의 체리픽은 Perforce, SVN 같은 기존 VCS의 체리픽과 다르게 동작한다.

기존 VCS는 특정 커밋을 체리픽하면 CL 사이의 변경 분이 반영되는데, 깃은 특정 커밋에 포함된 파일이 그대로 반영된다. 다시 말해, 1개의 커밋만 체리픽해도 그 이전 커밋에서 변경된 사항도 딸려온다.

rebase가 안된다?

>git checkout my_branch
>git merge master
There is no tracking information for the current branch.
Please specify which branch you want to rebase against.
See git-rebase(1) for details.

    git rebase <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=<remote>/<branch> my_branch

위와 같은 에러와 함께 안된다면, 공통 부모 커밋을 찾지 못해 rebase를 할 수 없다는 뜻이다.

위 예제에서는 my_branch가 master에서 가지쳐 나온 브랜치이고, 이 브랜치를 master에 rebase 시도 했다. 그러므로, rebase할 my_branch 브랜치 upstream 브랜치를 아래와 같이 정해주자.

>git branch -u master

커밋 메시지의 기본 에디터 변경

명령창을 통해 커밋 메시지를 작성할 때, 깃은 시스템 에디터를 사용한다. 다른 어플리케이션으로 에디터를 바꾸고 싶다면 core.editor를 바꾸면 된다.

>git config --global core.editor emacs

노트패드로 바꾸고 싶다면 아래와 같이 하면 된다.

>git config --global core.editor notepad

만약 path 선언이 안된 어플리케이션의 전체 경로를 입력하고 싶다면 아래와 같이 입력하자.

> git config --global core.editor "'C:\Sublime Text\subl.exe' -n -w"

바꾼 후, 커밋을 해보면 커밋 메시지를 통해 서브라임 텍스트로 수정할 수 있다. 그리고, 열린 파일을 저장 후 닫으면 커밋이 진행된다.

터미널에서 한글 안보이는 문제

깃은 인코딩을 변경하지 않는다. 라인 피드 이슈를 제외하고 말이다. 그러므로, 윈도우의 명령창(cmd 나 git-cmd)에서 한글이 안보이는 것은 깃이 아닌 다른 도구를 확인해야 한다.

만약, git-bash에서는 제대로 보이는데 명령창에서만 제대로 안보인다면 윈도우의 명령창이 참조하는 환경 변수으로 해결할 수 있다.

>set LC_ALL=C.UTF-8

참조

깃의 Detached HEAD

Detached HEAD란?

보통 브랜치(branch)는 특정 커밋(commit)의 revision number를 가리키고 HEAD가 이 브랜치를 가리킨다. 이렇게 HEAD -> 브랜치 -> 특정 커밋 순서로 commit을 가리키는 상태를 ‘attached HEAD’ 상태(state)라고 한다. 그리고, Detached HEAD란 HEAD가 브랜치를 통해 간접적으로 commit을 가리키지 않고, 직접 커밋을 가리키는 것을 말한다.

깃에서 HEAD는 1개 뿐이고, 이 HEAD는 현재 체크아웃(checkout)한 커밋을 가리킨다. 추가적인 작업을 위해 다른 브랜치를(깃 책들에서 자주 언급되는 예제 브랜치인 hotfix나 issue53같은) 체크아웃하면 HEAD는 체크아웃한 브랜치로 이동하며, 이 때 이전에 HEAD가 브랜치가 아닌 커밋을 직접가리키는 detached HEAD였다면 커밋의 revision number을 모르면 그 전으로 (쉽게) 돌아갈 수 없고, (기본적으로) 그래프에도 표시되지 않는다.

이런 명령어를 사용하면 detached HEAD 상태가 된다.

git checkout master^
git checkout HEAD~2
git checkout origin/master
git checkout <tag name>
git checkout <revision number>

커밋을 잃어버린 것인가?

커밋이 사라진 것은 아니다. 쉽게 돌아갈 수 없을 뿐 아래와 같은 명령어를 사용하면 내 HEAD가 이동했던 히스토리를 통해 이전 commit을 찾아 다시 가볼 수 있다.

>git reflog

그리고, 기본적인 커밋 그래프에서는 보이지 않지만, 명령어를 잘 만들면 그래프에서도 볼 수도 있다.

>git log --graph --decorate $(git rev-list -g --all)

(윈도우 사용자라면 git bash에서 실행하자.)

그럼 문제 없는 거 아닌가?

깃은 브랜치를 통해 커밋들을 관리한다. 그리고 Detached HEAD 커밋은 브랜치에 연결되어 있지 않아 관리가 불가능하다. 그래프에서도 보이지 않고, 브랜치를 이동하면 사라진다. 그저, 찾을 방법이 있다는 것이다. 무엇이 문제인지 이해가 되지 않는 이유는 다른 VCS(버전 컨트롤 시스템)과 깃의 차이점을 이해하지 못하는 것에서 발생하는 것 같다. 다른 VCS에서 HEAD는 시간의 순서에 따라 가장 마지막에 한 커밋을 가리키지만, 깃에서는 현재 체크아웃한 변경사항을 가리키기 때문에 브랜치를 통해 연결되어 있지 않은 커밋은 사용할 수 없다.

그럼 어떻게 해야 하지?

브랜치를 만들면 된다. 아래의 명령어 한 줄이면 브랜치를 만들고, 커밋을 살릴 수있다.

>git checkout -b <new branch name>

깃이 권장하는 방법이기도 하고 이를 위해 브랜치 만드는 비용(저장공간이나 컴퓨팅 파워)가 저렴하다. 커밋은 브랜치에 하고 혹시 모르는 사이에 detached HEAD가 된 커밋은 브랜치를 따로 만들거나 기존 브랜치에 변경사항을 이동하도록 하자.

참조