GitQuickStart

Clunix Wiki
(버전 사이의 차이)
(git pull & fetch 내용 추가)
(Windows 환경)
 
(사용자 2명의 중간의 편집 17개 숨겨짐)
2번째 줄: 2번째 줄:
 
연구소에서 git를 이용한  소스 코드 관리를 추진하고자 한다.
 
연구소에서 git를 이용한  소스 코드 관리를 추진하고자 한다.
 
git는 기능도 막강하고 무엇보다 분산 Version Control이 가능하여 개인별로 자유로운 버전 관리와 offline 모드 지원이 막강하다.
 
git는 기능도 막강하고 무엇보다 분산 Version Control이 가능하여 개인별로 자유로운 버전 관리와 offline 모드 지원이 막강하다.
 +
 +
* 연구소 공식 git 서버주소는 git (git.rnd.clunix.com, 192.168.12.11)이다.
 +
* git을 테스트할 수 있는 repository 주소는 git@git:testing
  
 
= git 설치 및 설정 =
 
= git 설치 및 설정 =
16번째 줄: 19번째 줄:
 
  $ git config --global core.editor vi
 
  $ git config --global core.editor vi
  
git repository 접근 하기 위해서는,
+
git repository 접근 하기 위해서는, 자신의 public key를 gitolite에 등록해야 한다. ssh public key를 만드는 방법은 [[SSHIntro|SSH 사용법 안내]] 페이지를 참고
자신의 ssh public key를 등록하여 repository에 대한 접근 권한을 획득해야 한다. ssh public key를 만드는 방법은 [[SSHIntro|SSH 사용법 안내]] 페이지를 참고
+
(현재 gitolite를 등록할 수 있는 사람은 cezanne임, 문의 필요)
  
 
== SSH config 설정 ==
 
== SSH config 설정 ==
32번째 줄: 35번째 줄:
 
* Git clone시에 생성한 ppk 파일을 지정하여 git clone
 
* Git clone시에 생성한 ppk 파일을 지정하여 git clone
 
[[파일:Gitppk.png]]
 
[[파일:Gitppk.png]]
 +
 +
 +
 +
* config 설정
 +
** commit message를 추가하기 위해 git config를 설정해준다.
 +
** Tortoise git -> Settings
 +
** Git Tab에서 User Info를 자신에 맞게 수정해준다.
 +
[[파일:Git_config2.png]]
  
 
= git help =
 
= git help =
44번째 줄: 55번째 줄:
  
 
* git(192.168.12.11) 서버로 부터 testing repository를 로컬상의 testing 폴더를 작업 폴더로 만든다.
 
* git(192.168.12.11) 서버로 부터 testing repository를 로컬상의 testing 폴더를 작업 폴더로 만든다.
 +
** svn과 달리 git사용자임을 유의해야 한다. 사용자 식별은 gitolite에 등록된 public key로 구분한다.
 +
** repository 전체 경로가 아닌 repository명만 써야 한다.(git 권한 툴인 gitolite 특성)
 
** git은 SVN과 달리 repository에 있는 전체 저장소를 가져온다.
 
** git은 SVN과 달리 repository에 있는 전체 저장소를 가져온다.
 
** repository의 하위 폴더 일부를 가져오는 방법은 없다. 대신 submodule 기능을 통하여 하위 repository를 만들수 있다.
 
** repository의 하위 폴더 일부를 가져오는 방법은 없다. 대신 submodule 기능을 통하여 하위 repository를 만들수 있다.
285번째 줄: 298번째 줄:
 
  # renamed:    test.c -> test1.c
 
  # renamed:    test.c -> test1.c
 
  #
 
  #
 +
 +
= git remote =
 +
원격 저장소 정보를 열람하는 방법은 아래와 같다.
 +
 +
$ git remote
 +
origin
 +
 +
이것은 단순히 원격 저장소명만을 나열한다. 좀 더 자세한 정보를 보고자 한다면
 +
 +
$ git remote show origin
  
 
= git pull =
 
= git pull =
304번째 줄: 327번째 줄:
  
 
  git fetch
 
  git fetch
 +
 +
= tagging =
 +
git은 tagging 기능을 다양한 방식으로 제공한다.
 +
* lightweight tag: 간편하게 tagging 하는 방식.
 +
* annotated tag: tagging에 대한 부가설명을 추가할 수 있는 방식
 +
 +
$ git tag
 +
 +
위 명령은 tag 목록을 열람할 수 있다. 패턴으로 tag 목록을 열람할 수도 있다.
 +
 +
$ git tag -l 'v1.3*'
 +
 +
light-weight tag를 추가하는 방법은 다음과 같다.
 +
 +
$ git tag mytag
 +
 +
annotated tag를 추가하는 방법은 다음과 같다.
 +
 +
$ git tag -a mytag
 +
 +
이 경우는 tagging message를 입력하는 editor가 구동된다. annotated는 tagger와 날짜, log등이 기록된다.
 +
 +
tag 정보는 git push시 자동으로 전달되지 않으며, 다음과 같이 명시적으로 tag 정보를 원격 저장소에 전달하여야 한다.
 +
 +
$ git push origin mytag
  
 
= branching =
 
= branching =
 +
== branch 관리 ==
 +
현재 branch 목록을 열람하는 방법은 다음과 같다.
 +
 +
$ git branch
 +
* master
 +
    somebr
 +
 +
저장소에는 두개의 branch가 있으며, 현재 master branch에 있음을 나타낸다. (앞의 *가 표시)
 +
 +
branch를 생성하는 방법은 다음과 같다.
 +
 +
$ git branch mybranch
 +
 +
이것은 단순히 branch를 생성한 것으로 현재 작업 폴더가 새로 생성된 branch로 이동하지는 않는다.
 +
 +
이동을 위해서는 git checkout 명령어를 사용한다.
 +
 +
$ git checkout mybranch
 +
 +
branch를 생성함과 동시에 해당 branch로 이동하고자 한다면
 +
 +
$ git checkout -b mybranch
 +
 +
특정 branch를 삭제하고자 한다면
 +
$ git branch -d mybranch
 +
 +
== merge ==
 +
 +
branch 내용을 merge하는 방법은 다음과 같다.
 +
 +
$ git merge mybranch
  
 
= stashing =
 
= stashing =
 +
git은 현재 진행중인 작업 폴더의 작업 내용을 잠시 저장하고 다른 branch나 혹은 해당 branch에서 임시 작업을 진행할 수 있다.
 +
 +
$ git stash
 +
 +
이 명령은 현재 변경된 파일을 잠시 저장하고, 작업 폴더의 내용은 변경 이전 상태로 돌려 놓는다.
 +
 +
$ git stash list
 +
 +
stashing 목록을 열람한다.
 +
stashing 목록에서 진행중이던 작업내용에 대한 설명글은 git가 자동적으로 생성하는데, 만약 특정 설명글을 부여하고 싶다면
 +
 +
$ git stash save 사용자 그룹 기능 구현중
 +
 +
stashing된 요약 내용을 보거나 변경사항을 보려면
 +
$ git stash show
 +
$ git stash show -p
 +
 +
저장된 작업 내용을 다시 작업 폴더에 적용하려면
 +
 +
$ git stash apply
 +
 +
이 명령은 가장 최근의 stashing을 적용하는 것으로 특정 stashing을 적용하려면 다음과 같이 수행할 수 있다.
 +
 +
$ git stash apply stash@{2}
 +
 +
만약 적용된 stashing을 다시 취소하려고 한다면
 +
 +
$ git stash show -p | git apply -R
 +
 +
적용을 하더라도 stashing은 계속 남아 있으며, 명시적으로 삭제를 해야 한다.
 +
 +
$ git stash drop
 +
 +
= Commit Guideline =
 +
* Remote Repo에 Checkin하는 단위(changeset)는 단일한 기능으로 구분하여 Commit하도록 한다.
 +
* commit 단위를 효과적으로 구성하기 위해서 staging area를 잘 활용하도록 한다.
 +
** 우선 정리된 파일은 add 명령을 통하여 staging area에 포함시킨다.
 +
** add 이후 변경된 부분만 working copy에서 확인 할 수 있다는 점도 편리하다.
 +
* 작업한 내용을 원격 repository로 push하는 경우 1기능 당 단일한 changeset으로 처리하도록 한다.
 +
* 이를 위해 master나 다른 development branch에 대해서 개인별 local branch를 생성하여 작업한다.
 +
** local branch에서는 개발자 개인의 상황에 따라 자유 자재로 commit이 가능하다.
 +
* local branch에서 모든 commit을 완료 한 후, upstream으로 이동하여(checkout) local branch를 merge한다.
 +
** 이 때 local branch의 여러 commit을 다음의 명령으로 단일 commit으로 squash 옵션을 제공한다.
 +
# git checkout master
 +
# git merge --squash mybranch
 +
* local branch에서는 필요에 따라 임의로 commit을 하고, 작업한 여러 commit들을 합쳐서 단일 commit으로 remote repository에 반영할 수 있는 것이다.
 +
** 공유되는 원격 repository는 정제된 changeset만 반영된다.
 +
** 과다한 changeset으로 인한 remote repository의 부하를 방지할 수 있다.
 +
 +
== mybranch 작업 시나리오 ==
 +
* master branch에 대한 개인 branch로 mybranch를 생성하여 2개의 commit을 mybranch에 올린 후 master에 merge하여 원격 repository에 push 과정까지를 살펴보기로 한다.
 +
* master로 branch를 옮겨서 원격 repository의 내용을 pull한다.
 +
# git checkout master
 +
Switched to branch 'master'
 +
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
 +
# git pull
 +
remote: Counting objects: 5, done.
 +
remote: Compressing objects: 100% (3/3), done.
 +
remote: Total 3 (delta 1), reused 0 (delta 0)
 +
Unpacking objects: 100% (3/3), done.
 +
From file:///home/cezanne/temp/repotest/repo
 +
    a759bd2..733001c  master    -> origin/master
 +
Updating a759bd2..733001c
 +
Fast-forward
 +
  test.c |    2 +-
 +
  1 file changed, 1 insertion(+), 1 deletion(-)
 +
 +
* 내가 작업한 local branch를 master branch로 merge한다.
 +
# git merge --squash mybranch
 +
Updating ecc08f0..2a5a39b
 +
Fast-forward
 +
Squash commit -- not updating HEAD
 +
  test.c  |    2 +-
 +
  test2.c |    2 +-
 +
  2 files changed, 2 insertions(+), 2 deletions(-)
 +
 +
* merge시 conflict가 없는 경우는 정상적으로 merge가 수행되며, 작업 디렉토리의 상태는 아래와 같이 된다.
 +
# git status
 +
# On branch master
 +
# Changes to be committed:
 +
#  (use "git reset HEAD <file>..." to unstage)
 +
#
 +
# modified:  test.c
 +
# modified:  test2.c
 +
#
 +
 +
* master로 merge된 내용을 최종적으로 commit한다.
 +
** commit log는 mybranch의 commit log들이 squash된 형태이므로 적절히 수정필요함
 +
# git commit
 +
[master e32aa6d] return 4 in test2.c, return 4 in test.c
 +
  2 files changed, 2 insertions(+), 2 deletions(-)
 +
 +
* merge시 conflict가 발생하면, merge시 아래와 같은 오류가 발생하며, conflict가 발생한 test.c는 status가 both modified로 표시된다.
 +
** test2.c 는 conflict없이 merge가 된 경우임
 +
# git merge --squash mybranch
 +
Auto-merging test.c
 +
CONFLICT (content): Merge conflict in test.c
 +
Squash commit -- not updating HEAD
 +
Automatic merge failed; fix conflicts and then commit the result.
 +
# git status
 +
# On branch master
 +
# Changes to be committed:
 +
#  (use "git reset HEAD <file>..." to unstage)
 +
#
 +
# modified:  test2.c
 +
#
 +
# Unmerged paths:
 +
#  (use "git reset HEAD <file>..." to unstage)
 +
#  (use "git add/rm <file>..." as appropriate to mark resolution)
 +
#
 +
# both modified:      test.c
 +
#
 +
 +
* conflict가 발생한 test.c는 해당 코드 부분을 정리한 후, conflict가 resolve된 것으로 add를 수행한다.
 +
** test.c의 내용은 다음과 같이 표시됨
 +
#include <stdio.h>
 +
 +
<<<<<<< HEAD
 +
func(int a, const char *str)
 +
=======
 +
func(int a, char *arg)
 +
>>>>>>> mybranch
 +
{
 +
}
 +
 +
* conflict를 모두 처리한 후 test.c를 add한다.
 +
# git add test.c
 +
* add 한 이후 commit을 수행(local master에 checkin 하는 작업)
 +
** commit message는 아래와 같은 형태가 된다.
 +
 +
Conflicts:
 +
        test.c
 +
 +
# Please enter the commit message for your changes. Lines starting
 +
# with '#' will be ignored, and an empty message aborts the commit.
 +
# On branch master
 +
# Changes to be committed:
 +
#  (use "git reset HEAD <file>..." to unstage)
 +
#
 +
#      modified:  test.c
 +
#      modified:  test2.c
 +
#
 +
 +
* 기존 mybranch에서 commit된 로그 내용이 축약된 형태로 표시되지 않으므로, 직접 mybranch에서 log들을 참조하여 적절히 로그를 작성하도록 한다.
 +
* 이 후 master의 내용을 push한다.
 +
 +
# git push
 +
Counting objects: 7, done.
 +
Delta compression using up to 8 threads.
 +
Compressing objects: 100% (4/4), done.
 +
Writing objects: 100% (4/4), 452 bytes, done.
 +
Total 4 (delta 1), reused 0 (delta 0)
 +
Unpacking objects: 100% (4/4), done.
 +
To file:///home/cezanne/temp/repotest/repo
 +
    1a7d9cd..f50c313  master -> master
 +
 +
* mybranch는 다시 현재의 master 내용으로 branch를 만든다.
 +
** mybranch가 기존에 존재하므로 -f option을 사용하여 강제로 mybranch를 생성하도록 해야 한다.
 +
# git branch -f mybranch
 +
 +
* 만약 push과정에서 다른 commit이 그 사이에 다시 반영될 수 있다. 이 경우는 아래와 같은 메시지가 나타난다.
 +
# git push
 +
To file:///home/cezanne/temp/repotest/repo
 +
  ! [rejected]        master -> master (non-fast-forward)
 +
error: failed to push some refs to 'file:///home/cezanne/temp/repotest/repo'
 +
hint: Updates were rejected because the tip of your current branch is behind
 +
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
 +
hint: before pushing again.
 +
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
 +
 +
* 이 경우는 fetch를 수행하여 origin/master의 최신본을 가져오고, rebase를 수행하여 현재 local의 master branch를 origin/master 에 기반하도록 한다.
 +
# git fetch
 +
remote: Counting objects: 5, done.
 +
remote: Compressing objects: 100% (3/3), done.
 +
remote: Total 3 (delta 1), reused 0 (delta 0)
 +
Unpacking objects: 100% (3/3), done.
 +
From file:///home/cezanne/temp/repotest/repo
 +
    f50c313..843069d  master    -> origin/master
 +
# git rebase
 +
First, rewinding head to replay your work on top of it...
 +
Applying: add comment
 +
Using index info to reconstruct a base tree...
 +
Falling back to patching base and 3-way merge...
 +
Auto-merging test.c

2014년 5월 15일 (목) 11:12 현재 판

목차

서론

연구소에서 git를 이용한 소스 코드 관리를 추진하고자 한다. git는 기능도 막강하고 무엇보다 분산 Version Control이 가능하여 개인별로 자유로운 버전 관리와 offline 모드 지원이 막강하다.

  • 연구소 공식 git 서버주소는 git (git.rnd.clunix.com, 192.168.12.11)이다.
  • git을 테스트할 수 있는 repository 주소는 git@git:testing

git 설치 및 설정

Linux 환경

Linux 환경에서는 기본적으로 git 프로그램이 설치되어 있다. 만약 설치되어 있지 않다면 Ubuntu 의 경우 다음 패키지를 설치한다.

$ sudo apt-get install git

git을 이용한 commit시 사용되는 기본적인 설정 정보인 사용자 이름과 이메일, commit log 메시지를 작성하는 editor를 등록한다. 설정한 정보는 사용자 홈의 .gitconfig 파일에 기록된다.

$ git config --global user.name "KyungWoon Cho"
$ git config --global user.email "cezanne@clunix.com"
$ git config --global core.editor vi

git repository 접근 하기 위해서는, 자신의 public key를 gitolite에 등록해야 한다. ssh public key를 만드는 방법은 SSH 사용법 안내 페이지를 참고 (현재 gitolite를 등록할 수 있는 사람은 cezanne임, 문의 필요)

SSH config 설정

보통 ssh client 설정에서 X11 forward는 하지 않도록 다음과 같이 설정한다.

Host git 192.168.12.11
        ForwardX11 no

Windows 환경

  • msysgit(Git for windows) 설치, http://code.google.com/p/msysgit/
    • 설치시 행종결자 처리에 대한 옵션을 설정하는데, 3번째 옵션인 변환을 하지 않는 것이 바람직
  • TortoiseGit 설치
  • Putty용 private key 파일인 ppk 파일 생성. 생성 과정은 PPKGen을 참조
  • Git clone시에 생성한 ppk 파일을 지정하여 git clone

Gitppk.png


  • config 설정
    • commit message를 추가하기 위해 git config를 설정해준다.
    • Tortoise git -> Settings
    • Git Tab에서 User Info를 자신에 맞게 수정해준다.

Git config2.png

git help

  • git 명령 목록은 단순히 git을 입력 하면된다.
  • git 명령 --help 를 하면 manual page 화면이 수행된다.

git clone

  • git clone 명령은 svn checkout과 유사한 명령이다.
  • 원격 git repository로 부터 로컬에 저장소를 만든다.
$ git clone git@git:testing testing
  • git(192.168.12.11) 서버로 부터 testing repository를 로컬상의 testing 폴더를 작업 폴더로 만든다.
    • svn과 달리 git사용자임을 유의해야 한다. 사용자 식별은 gitolite에 등록된 public key로 구분한다.
    • repository 전체 경로가 아닌 repository명만 써야 한다.(git 권한 툴인 gitolite 특성)
    • git은 SVN과 달리 repository에 있는 전체 저장소를 가져온다.
    • repository의 하위 폴더 일부를 가져오는 방법은 없다. 대신 submodule 기능을 통하여 하위 repository를 만들수 있다.

git add

  • git은 repository에 commit을 하기전 저장공간인 staging area를 둔다.
  • 신규 생성된 파일이나 기존에 존재하던 파일이라도 수정한 내용을 commit하기 위해서는 반드시 add 과정을 거쳐야 한다.
$ git add test.c
  • 추가할 항목은 여러개나 glob 패턴도 가능하다.
$ git add test.c blah*.txt
  • 이미 추가한 항목에 대해서는 별도로 오류를 발생하지 않고, 무시한다.

git status

  • git status 는 현재 작업 폴더의 상태를 나타낸다.
  • svn과 달리 상태 화면이 좀 복잡하다.
$ git status
# On branch master
nothing to commit (working directory clean)

위의 경우는 폴더에 어떠한 파일도 없거나 수정한 것이 없는 경우

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	mytest.c
nothing added to commit but untracked files present (use "git add" to track)

mytest.c가 존재하지만, git으로 관리되지 않는 상태이다.

$ git add mytest.c
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   mytest.c
#

위의 mytest.c를 staging area에 add한 경우의 status 출력 결과이다.

기존 repository에 있는 파일을 수정한 경우라면 다음과 같은 출력 결과가 표시된다.

# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   test.c
#
no changes added to commit (use "git add" and/or "git commit -a")

위의 경우는 기존에 존재하는 파일인 test.c를 수정한 경우의 status 출력 결과이다.

이 파일을 add하면 다음과 같은 출력결과가 표시된다.

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   test.c
#

git diff

편집한 내용을 확인시에는 git diff를 사용한다.

$ git diff
diff --git a/test.c b/test.c
index 71ce22d..a32214c 100644
--- a/test.c
+++ b/test.c
@@ -1,3 +1,5 @@
+#include <stdio.h>
+
 void
 main()
 {

git diff는 staging area에 포함되지 않은 내용에 대해서만 diff 를 수행한다. 만약 staging area에 있는 내용에 대해서 diff를 원한다면 다음과 같이 수행한다.

git diff --cached

특정 파일의 diff만을 보고자 한다면 해당 파일을 인자로 부여한다.

git commit

commit 과정

git commit은 staging area에 있는 변경 내용을 repository로 commit한다.

$ git commit
[master 1bf0f40] test is just test
 1 file changed, 2 insertions(+)

git commit을 수행하면 commit log를 입력하는 editor가 수행되고, editor를 저장후 종료하면 commit 과정이 완료된다. 아래는 commit 수행시 log 입력 화면예시이다.

this is test
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   test.c
#

'this is test'라는 로그메시지를 입력한 화면이며, 아래쪽 #이 표시된 영역은 단순 설명으로서 commit log에 반영되지 않는다.

  • editor 편집을 취소하면 commit 과정은 자동 취소된다.
  • staging area에 반영된 내용만 commit된다. staging area에 반영되지 않는 편집된 내용은 commit되지 않음을 유의해야 한다.
  • commit도 일부 파일만 가능하며, 인자 없이 수행하면 staging area에 있는 전제 내용이 commit된다.

만약 staging area를 거치지 않고, 변경되거나 삭제된 파일을 일괄적으로 commit하고자 한다면 다음 명령을 수행한다.

$ git commit -a
  • 이 명령은 새로 생성된 파일(untracked file)을 자동으로 commit하지는 않는다.
  • staging area에 있는 변경파일도 동시에 commit된다.
  • 일부 파일만 일괄적으로 적용할 수는 없으며, 전체 변경되거나 삭제된 파일을 대상으로 적용된다.

commit 전 확인 사항

협업시 공백라인이나 공백문자에 의해 변경되는 코드들은 매우 성가신 일이다. commit 전 이러한 부분이 없는지 반드시 아래 명령으로 확인을 하도록 한다.

$ git diff --check

변경사항들은 논리적인 단위로 구분해서 commit을 하도록 한다. 여러개의 이슈가 섞인 형태의 commit은 지양한다. git은 이를 위한 다양한 기능들을 제공한다.

commit 메시지는 해당 작업을 잘 표현할 수 있게끔 작성한다. 첫줄에 35글자 이하로 해당 작업 한줄로 요약한다. (영문의 경우라면 50이하) 좀 더 상세한 메시지는 한줄 공백 후 상세 내용을 작성한다.

좋은 commit 메시지의 예시

Short (50 chars or less) summary of changes
  
More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Further paragraphs come after blank lines.

  - Bullet points are okay, too

  - Typically a hyphen or asterisk is used for the bullet, preceded by a
    single space, with blank lines in between, but conventions vary here

git log

commit log를 확인하는 방법은 git log 를 이용한다. git log는 터미널 화면에 맞는 만큼만 출력해서 보여준다.

$ git log

diff를 함께 보고자 하는 경우는 다음과 같이 수행한다. 양이 많은 경우 자동으로 paging 기능을 제공한다.

$ git log -p

최근 몇개만을 보고자 하는 경우는 다음과 같이 수행한다.

$ git log -2

git push

  • git 분산 버전 관리도구이다. commit을 하더라도 원격지 repository에 반영되지 않고, 로컬 repository에 commit이 된 것이다.
  • 로컬 repository에 반영된 commit 내용을 원격지 repository에 반영하기 위해서는 git push 명령을 수행한다.
$ git push
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 298 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@git:testing
   e0ab7f0..1bf0f40  master -> master

작업 내용 되돌리기

마지막 commit한 내용을 수정하고자 한다면 다음과 같이 수행한다.

$ git commit --amend
  • 위 명령은 staging area에 있는 변경된 내용을 마지막 commit에 적용한다.
  • 마지막 commit 내용중 변경되지 않는 부분은 영향을 받지 않는다.
  • 만약 변경된 내용이 없다면 단순히 commit log만을 수정하는 것이다.

staging area에 있는 내용을 다시 되돌리는 경우에는 다음과 같이 명령을 수행한다.

$ git reset HEAD <file>...

수정된 내용을 되돌리는 방법(svn revert와 같은 효과)은 다음과 같다. (마이너스 2번)

$ git checkout -- <file>

파일 삭제 및 이동

파일을 repository상에서 삭제하고자 하는 경우 먼저 파일을 삭제한다.

$ rm test.c
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	deleted:    test.c
#
no changes added to commit (use "git add" and/or "git commit -a")

파일 삭제 후 상태를 확인하면 deleted로 표시되며, 이를 staging area에 반영한다.

$ git rm test.c
rm 'test.c'
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	deleted:    test.c
#

이후 commit을 하면 test.c 삭제가 repository에 반영된다.

만약 디스크상에서 파일을 삭제하지 않고, 단순히 repository에서 파일을 제거하고자 한다면 다음과 같이 수행한다.

$ git rm --cached test.c

파일 삭제 없이 test.c 파일이 삭제되었음을 staging area에 반영한다. 이후 commit시 repository에 반영된다.

이름을 변경하고자 하는 경우에는 다음과 같이 수행한다.

$ git mv test.c test1.c
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	renamed:    test.c -> test1.c
#

git remote

원격 저장소 정보를 열람하는 방법은 아래와 같다.

$ git remote
origin

이것은 단순히 원격 저장소명만을 나열한다. 좀 더 자세한 정보를 보고자 한다면

$ git remote show origin

git pull

원격지의 repository에서 update하는 방법은 다음과 같다.(svn update와 같은 효과)

$ git pull

이 명령은 원격 저장소로 부터 변경된 내용을 로컬 저장소로 업데이트하며, 변경된 내용을 현재의 작업 폴더에 merge한다. 만약 conflict가 발생한다면 아래와 같은 오류 메시지가 나타나며, merge가 되지 않는다.

Updating 1bf0f40..80387cd
error: Your local changes to the following files would be overwritten by merge:
	test.c
Please, commit your changes or stash them before you can merge.
Aborting

만약 merge하지 않고, 원격저장소로 부터 변경분만 로컬저장소에 저장한다면 다음과 같이 수행한다.

git fetch

tagging

git은 tagging 기능을 다양한 방식으로 제공한다.

  • lightweight tag: 간편하게 tagging 하는 방식.
  • annotated tag: tagging에 대한 부가설명을 추가할 수 있는 방식
$ git tag

위 명령은 tag 목록을 열람할 수 있다. 패턴으로 tag 목록을 열람할 수도 있다.

$ git tag -l 'v1.3*'

light-weight tag를 추가하는 방법은 다음과 같다.

$ git tag mytag

annotated tag를 추가하는 방법은 다음과 같다.

$ git tag -a mytag

이 경우는 tagging message를 입력하는 editor가 구동된다. annotated는 tagger와 날짜, log등이 기록된다.

tag 정보는 git push시 자동으로 전달되지 않으며, 다음과 같이 명시적으로 tag 정보를 원격 저장소에 전달하여야 한다.

$ git push origin mytag

branching

branch 관리

현재 branch 목록을 열람하는 방법은 다음과 같다.

$ git branch
* master
   somebr

저장소에는 두개의 branch가 있으며, 현재 master branch에 있음을 나타낸다. (앞의 *가 표시)

branch를 생성하는 방법은 다음과 같다.

$ git branch mybranch

이것은 단순히 branch를 생성한 것으로 현재 작업 폴더가 새로 생성된 branch로 이동하지는 않는다.

이동을 위해서는 git checkout 명령어를 사용한다.

$ git checkout mybranch

branch를 생성함과 동시에 해당 branch로 이동하고자 한다면

$ git checkout -b mybranch

특정 branch를 삭제하고자 한다면

$ git branch -d mybranch

merge

branch 내용을 merge하는 방법은 다음과 같다.

$ git merge mybranch

stashing

git은 현재 진행중인 작업 폴더의 작업 내용을 잠시 저장하고 다른 branch나 혹은 해당 branch에서 임시 작업을 진행할 수 있다.

$ git stash

이 명령은 현재 변경된 파일을 잠시 저장하고, 작업 폴더의 내용은 변경 이전 상태로 돌려 놓는다.

$ git stash list

stashing 목록을 열람한다. stashing 목록에서 진행중이던 작업내용에 대한 설명글은 git가 자동적으로 생성하는데, 만약 특정 설명글을 부여하고 싶다면

$ git stash save 사용자 그룹 기능 구현중
stashing된 요약 내용을 보거나 변경사항을 보려면 
$ git stash show
$ git stash show -p

저장된 작업 내용을 다시 작업 폴더에 적용하려면

$ git stash apply

이 명령은 가장 최근의 stashing을 적용하는 것으로 특정 stashing을 적용하려면 다음과 같이 수행할 수 있다.

$ git stash apply stash@{2}

만약 적용된 stashing을 다시 취소하려고 한다면

$ git stash show -p | git apply -R

적용을 하더라도 stashing은 계속 남아 있으며, 명시적으로 삭제를 해야 한다.

$ git stash drop

Commit Guideline

  • Remote Repo에 Checkin하는 단위(changeset)는 단일한 기능으로 구분하여 Commit하도록 한다.
  • commit 단위를 효과적으로 구성하기 위해서 staging area를 잘 활용하도록 한다.
    • 우선 정리된 파일은 add 명령을 통하여 staging area에 포함시킨다.
    • add 이후 변경된 부분만 working copy에서 확인 할 수 있다는 점도 편리하다.
  • 작업한 내용을 원격 repository로 push하는 경우 1기능 당 단일한 changeset으로 처리하도록 한다.
  • 이를 위해 master나 다른 development branch에 대해서 개인별 local branch를 생성하여 작업한다.
    • local branch에서는 개발자 개인의 상황에 따라 자유 자재로 commit이 가능하다.
  • local branch에서 모든 commit을 완료 한 후, upstream으로 이동하여(checkout) local branch를 merge한다.
    • 이 때 local branch의 여러 commit을 다음의 명령으로 단일 commit으로 squash 옵션을 제공한다.
# git checkout master
# git merge --squash mybranch
  • local branch에서는 필요에 따라 임의로 commit을 하고, 작업한 여러 commit들을 합쳐서 단일 commit으로 remote repository에 반영할 수 있는 것이다.
    • 공유되는 원격 repository는 정제된 changeset만 반영된다.
    • 과다한 changeset으로 인한 remote repository의 부하를 방지할 수 있다.

mybranch 작업 시나리오

  • master branch에 대한 개인 branch로 mybranch를 생성하여 2개의 commit을 mybranch에 올린 후 master에 merge하여 원격 repository에 push 과정까지를 살펴보기로 한다.
  • master로 branch를 옮겨서 원격 repository의 내용을 pull한다.
# git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
# git pull 
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From file:///home/cezanne/temp/repotest/repo
   a759bd2..733001c  master     -> origin/master
Updating a759bd2..733001c
Fast-forward
 test.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
  • 내가 작업한 local branch를 master branch로 merge한다.
# git merge --squash mybranch
Updating ecc08f0..2a5a39b
Fast-forward
Squash commit -- not updating HEAD
 test.c  |    2 +-
 test2.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
  • merge시 conflict가 없는 경우는 정상적으로 merge가 수행되며, 작업 디렉토리의 상태는 아래와 같이 된다.
# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   test.c
#	modified:   test2.c
#
  • master로 merge된 내용을 최종적으로 commit한다.
    • commit log는 mybranch의 commit log들이 squash된 형태이므로 적절히 수정필요함
# git commit
[master e32aa6d] return 4 in test2.c, return 4 in test.c
 2 files changed, 2 insertions(+), 2 deletions(-)
  • merge시 conflict가 발생하면, merge시 아래와 같은 오류가 발생하며, conflict가 발생한 test.c는 status가 both modified로 표시된다.
    • test2.c 는 conflict없이 merge가 된 경우임
# git merge --squash mybranch
Auto-merging test.c
CONFLICT (content): Merge conflict in test.c
Squash commit -- not updating HEAD
Automatic merge failed; fix conflicts and then commit the result.
# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   test2.c
#
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#	both modified:      test.c
#
  • conflict가 발생한 test.c는 해당 코드 부분을 정리한 후, conflict가 resolve된 것으로 add를 수행한다.
    • test.c의 내용은 다음과 같이 표시됨
#include <stdio.h>

<<<<<<< HEAD
func(int a, const char *str)
=======
func(int a, char *arg)
>>>>>>> mybranch
{
}
  • conflict를 모두 처리한 후 test.c를 add한다.
# git add test.c
  • add 한 이후 commit을 수행(local master에 checkin 하는 작업)
    • commit message는 아래와 같은 형태가 된다.
Conflicts:
        test.c
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   test.c
#       modified:   test2.c
#
  • 기존 mybranch에서 commit된 로그 내용이 축약된 형태로 표시되지 않으므로, 직접 mybranch에서 log들을 참조하여 적절히 로그를 작성하도록 한다.
  • 이 후 master의 내용을 push한다.
# git push
Counting objects: 7, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 452 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
To file:///home/cezanne/temp/repotest/repo
   1a7d9cd..f50c313  master -> master
  • mybranch는 다시 현재의 master 내용으로 branch를 만든다.
    • mybranch가 기존에 존재하므로 -f option을 사용하여 강제로 mybranch를 생성하도록 해야 한다.
# git branch -f mybranch
  • 만약 push과정에서 다른 commit이 그 사이에 다시 반영될 수 있다. 이 경우는 아래와 같은 메시지가 나타난다.
# git push
To file:///home/cezanne/temp/repotest/repo
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'file:///home/cezanne/temp/repotest/repo'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
  • 이 경우는 fetch를 수행하여 origin/master의 최신본을 가져오고, rebase를 수행하여 현재 local의 master branch를 origin/master 에 기반하도록 한다.
# git fetch
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From file:///home/cezanne/temp/repotest/repo
   f50c313..843069d  master     -> origin/master
# git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging test.c
부서별 위키