==기본적인 요령==

Git 명령어의 바다 속에 곧바로 빠지는 것 보단, 다음 기본적인 예제를 통해서
천천히 배우는 방법이 좋을 것입니다. 표면적으로는 간단하게 보이지만, 이 곳 예제들은 앞으로 많은 도움이 될 것입니다.
저 역시도 처음 Git을 사용할 때에는 아래에 있는 예제 외에 다른 것들은 건들여 보지도 않았습니다.

=== 상태 (state) 저장하는 방법===

무엇인가 대단한 것을 해보고 싶으시다고요? 그러시기 전에, 현 디렉토리에 들어있는
모든 파일의 스냅샷을 찍어봅시다:

 $ git init
 $ git add .
 $ git commit -m "My first backup"

만약에 편집을 하다가 잘 못됬다면, 예전의 편집되기 전의 깨끗한 버전을 되돌리면 됩니다:

 $ git reset --hard

다시 state를 저장하고 싶다면:

 $ git commit -a -m "Another backup"

=== 파일 더하기 (add), 지우기 (delete), 이름 바꾸기 (rename) ===

위의 간단한 요령들은 처음 *git add* 명령어를 실행했을 때 이미 존재하던 파일들만 저장하게 됩니다. 새로운 파일들이나 하위 디렉토리들을 추가했다면:

 $ git add readme.txt Documentation

그리고 만약에 원하지 않는 파일을 Git에서 없애려면:

 $ git rm kludge.h obsolete.c
 $ git rm -r incriminating/evidence/

이렇게 함으로써 Git은 지정한 파일들을 지워주게 됩니다.

파일 이름바꾸기는 원치않는 현재의 이름을 지우고 새로운 이름을 새롭게 지정하는 컨셉과 같습니다. 좀 더 손쉬운 방법으로는 *git mv* 명령어가 있습니다. 예를 들어:

 $ git mv bug.c feature.c

=== 고급 undo와 redo ===

가끔씩은 작업을 하다가 하던 일을 멈추고 전 버전으로 돌아가고 싶다거나, 한 시점 이후의 모든 편집을 지우고 싶을 때가 있을 것입니다. 그렇다면:

 $ git log

이 명령어는 최근에 commit들을 정리한 리스트와 그의 SHA1을 보여줍니다.

----------------------------------
commit 766f9881690d240ba334153047649b8b8f11c664
Author: Bob <bob@example.com>
Date:   Tue Mar 14 01:59:26 2000 -0800

    Replace printf() with write().

commit 82f5ea346a2e651544956a8653c0f58dc151275c
Author: Alice <alice@example.com>
Date:   Thu Jan 1 00:00:00 1970 +0000

    Initial commit.
----------------------------------

Hash 앞의 알파벳 몇 개만으로도 commit을 세분화 설정하실 수 있습니다;
다른 방법으로는, hash 전문을 복사/붙여넣기 하는 방법도 있지요:

 $ git reset --hard 766f

위 명령어를 입력하시면 설정된 commit으로 돌아갈 수 있으며 그 후의 새로운 commit들은 영구적으로 삭제됩니다.

가끔씩은 또 아주 예전의 state로 잠시만 돌아가길 원하실 수 있습니다. 그럴 경우에는:

 $ git checkout 82f5

이 명령어는 새로운 commit들을 보존함과 동시에 과거의 시간으로 잠시 돌아가게 해줍니다. 그러나, SF영화에서 처럼, 과거에 돌아간 상태에서 편집을하고 commit을 한다면 다른 시간대의 현실을 만들어가게 되는 것이죠. 왜냐하면 당신의 편집이 과거의 편집과는 다르게 입력이 되었기 때문입니다.

이런 대체현실을 'branch (나뭇가지)'라고 부릅니다 <<branch>>에 관해선 추후에 자세히 설명합니다>>. 지금 알고계셔야 할 것은

 $ git checkout master

이 것은 현재시간의 state로 오게 해줄 것입니다. 그리고 Git이 푸념을 놓기전에 편집했던 사항들이 있다면
master branch로 돌아오기전 commit을 하거나 reset을 하시길 바랍니다.
 
컴퓨터 게임과 또 다시 비교해본다 하면:

- *`git reset --hard`*: 예전에 세이브 해뒀던 게임으로 돌아가며, 돌아간 시점 이후의 세이브들을 모두 삭제합니다.

- *`git checkout`*: 예전에 세이브 해뒀던 게임으로 돌아가며, 돌아간 시점 이후의 게임들은 처음 세이브와 다른 길을 가게 됩니다. 추후의 모든 세이브들은 다른 branch로써 새로운 현실세계를 만들게 됩니다 <<branch>>에 관해선 추후에 자세히 설명합니다>>.

예전의 파일/하위 디렉토리들을 되돌리고 싶을 때 다음 명령어를 이용함으로써 필요한 파일/하위 디렉토리만을 되돌릴 수 있습니다:

 $ git checkout 82f5 some.file another.file

그러나 이 *checkout* 핸들이 다른 파일들을 조용히 덮어씌우기 할 수 있다는 점을 알아두세요. 이러한 사고를 방지하고 싶다면
checkou 명령어를 쓰기전에 commit을 이용하세요. Git을 처음 이용하는 분들은 특히 더 조심하시기 바랍니다.
대체적으로 파일이 삭제될까 두려우시다면 *git commit -a*를 우선해놓고 생각하세요. 

Hash를 자르고 붙여넣기 싫으시다고요? 그렇다면:

 $ git checkout :/"My first b"

이 명령어를 사용함으로써 이 message로 commit을 해두었던 state로 돌아갈 수 있습니다.
그리고 이 다음 명령어로 5번 스텝 전의 state로 돌아갈 수도 있습니다:

 $ git checkout master~5

=== 되돌리기 (Reverting) ===

법정에서는 어떠한 일에 관해서는 기록에서 지울 수 있습니다. 이런 식으로, Git에서는 원하는 commit을 정해서 없던 일로 할 수 있습니다.

 $ git commit -a
 $ git revert 1b6d

이렇게 하는 것으로 특정 hash에 대한 commit을 undo 할 수 있습니다. 이렇게 되돌린 state는 새로운 
commit으로 인식되어 *git log*에 기록됩니다.
 
=== 변경기록 만들기 ===

어떤 프로젝트들은  http://en.wikipedia.org/wiki/Changelog[changelog]. 필요로 합니다.
다음 명령어를 이용해 변경기록을 만들어 봅시다.:

 $ git log > ChangeLog

=== 파일 다운로드하기 ===

Git으로 관리되는 프로젝트 사본을 얻기위해서는:

 $ git clone git://server/path/to/files

예를 들어, 본 웹사이트를 만들기 위해 사용한 파일들을 얻기위해서는:

 $ git clone git://git.or.cz/gitmagic.git

곧 *clone* 명령어에 관해 많은 것을 소개하도록 하겠습니다.

=== 최첨단 기술 ===

*git clone* 명령어를 이용해 어떤 프로젝트의 사본을 다운로드했다면, 다음 명령어를 이용해 그 프로젝트의 최신버전으로 업그레이드 할 수 있습니다:

 $ git pull

=== 즉석 발행 ===

당신이 다른 사람들과 공유하고 싶은 스크립트를 작성했다고 가정합니다. 당신은 그들에게 당신의 컴퓨터에서 다운로드를 받으라고 할 수있지만, 당신 친구들이 만약 당신이 편집하는 도중에 받게된다면, 그들은 예상치 못 한 트러블에 걸릴 수 있습니다. 이러한 이유 때문에 릴리스 사이클이란 것이 존재하는 것입니다. 개발자들은 개발 중인 프로젝트에 자주 들락날락 거릴 것이고, 그들은 남 앞에 내놓을 만한 프로젝트로 만들어지기 전까지 남들에게 보여주게 되지 않을겁니다.

Git으로 이런 문제를 해결할려면, 당신의 스크립트가 들어있는 디렉토리에서:

 $ git init
 $ git add .
 $ git commit -m "First release"

그리고 당신들 친구들에게 다음 명령어를 사용하도록 하십시오:

 $ git clone your.computer:/path/to/script

그들이 이렇게하면 당신의 스크립트를 다운로드 할 수 있을 것입니다. 이 작업은 ssh 접근을 가정합니다. 그렇지 않다면, 당신은 *git daemon* 명령어를 쓴 후 친구들에게 다음 명령어를 써보라고 합니다:

 $ git clone git://your.computer/path/to/script

이렇게 하고 난 다음부터 당신의 스크립트가 준비되었을 때마다 다음 명령어를 실행하면 됩니다:

 $ git commit -a -m "Next release"

당신의 친구들은 다음 명령어를 사용함으로써 가장 최근 버전으로 당신의 스크립트를 보유하고 있을 수 있게 되죠:

 $ git pull

그들은 절대로 당신이 보여주고 싶지않은 버전의 스크립트를 보는 일이 없을 것입니다.

=== 제가 도대체 뭘 한거죠? ===

마지막으로 한 commit으로 부터 어떤 변화가 있었는지 확인하기 위해서는:

 $ git diff

아니면 어제부터 어떤 변화가 있었는지 확인하기 위해서는:

 $ git diff "@{yesterday}"

아니면 어떤 특정 버전에서 부터 2번째 전 버전 사이의 변화를 확인하기 위해서는:

 $ git diff 1b6d "master~2"

각각의 결과는 *git apply*와 함께 적용할 수 있는 패치가 될 것입니다.
 다음 명령어도 사용해 보세요:

 $ git whatchanged --since="2 weeks ago"

저는 가끔씩 http://sourceforge.net/projects/qgit[qgit] 에 들어가서 히스토리를 체크하곤 합니다. 이 웹사이트는 깨끗한 그래픽 인터페이스로 구성되어 있어 보기 쉽지요. 아니면, http://jonas.nitro.dk/tig/[tig], 텍스트형식 인터페이스 역시 느린 연결방식을 가지고 있는 분들에겐 도움이 될 것입니다. 또 다른 방법으로는 웹 서버를 설치한 후 *git instaweb*명령어를 사용하는 방법도 있겠지요.

=== 연습 ===

우선 A, B, C, D 를 각각 연속된 commit이라고 가정합니다. 그리고 B는 A 에서 몇 개의 파일들이 삭제된 버전으로 가정합니다. 문제는 여기서 몇몇 파일들을 D에 더하고 싶을 때 어떻게 하는건가 입니다.

세가지의 해답을 찾을 수 있겠군요. 우선 우리가 현재 D에 있다고 생각합시다:

  1. A와 B의 차이점은 몇 개의 파일들이 없어진 것 뿐입니다. 우리는 이 차이점을 패치로 작성하여 적용할 수 있습니다.:

   $ git diff B A | git apply

  2. 우리는 A에 파일을 저장해 두었기에, 그 곳에서 다시 받아올 수 있겠지요:

   $ git checkout A foo.c bar.h

  3. 또는 A에서 B까지로 갈 때의 변화를 undo한다고 생각하셔도 됩니다:

   $ git revert B

어떤 방법이 가장 좋은 해답일까요? 답은 본인이 원하는 것이 곧 해답입니다. Git을 이용한다면 당신이 원하는 것은 쉽게 해낼 수 있고, 그 것을 해내는 방법은 한가지만 있는 것이  아닐 겁니다.
