Git

From 탱이의 잡동사니
Revision as of 21:20, 12 August 2019 by Pchero (talk | contribs) (→‎set-url)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Overview

Git 사용법 정리.

Basic

Trees

branching model

git 은 일반적으로 세가지 트리를 관리하는 시스템이다.

  • HEAD : Role.
  • Index : 마지막 커밋 스냅샵, 다음 커밋의 부모 커밋.
  • Working Directory : 다음에 커밋할 스냅샷

HEAD

HEAD는 현재 브랜치를 가리키는 포인터이며, 브랜치에 담긴 커밋 중 가작 마지막 커밋을 가리킨다. 지금의 HEAD가 가리키는 커밋은 바로 다음 커밋의 부모가 된다. 단순하게 생각하면 HEAD 는 마지막 커밋의 스냅샷이다. HEAD기 가리키는 스냅샷을 살펴보기는 쉽다. 아래는 HEAD 스냅샷의 디렉토리 리스팅과 각 파일의 SHA-1 체크섬을 보여주는 예제다.

$ git cat-file -p HEAD
tree 388d18182352b623ae494e5db098a9234572c1c0
parent 6cb15d5061504f012a22528fc77d02a29005ce61
author pchero <pchero21@gmail.com> 1431027284 +0200
committer pchero <pchero21@gmail.com> 1431027284 +0200

Added null paramater access control.

- If get null byte, just return null


$ git ls-tree -r HEAD
100755 blob c57d76c4bfef251a72818044af96dea2af3e4fb0	Makefile
100755 blob de92fb96b5a3088c7d762e6ec8da3e946e94047a	README
100755 blob 031939c8afccd8bb862eac748aa075d2831eb985	conf/zmq_manager.conf

Index

Index 는 바로 다음에 커밋할 것들이다. 바로 Staging Area 이다. Staging Area 는 사용자가 git commit 명령을 실행했을 때 git이 처리할 것들이 있는 곳이다.

먼저 Index 는 워킹 디렉토리에서 마지막으로 Checkout 한 브랜치의 파일 목록과 파일 내용으로 채워진다. 이후 파일 변경작업을 하고 변경한 내용으로 Index 를 업데이트 할 수 있다. 이렇게 업데이트하고 git commit 명령을 실행하면 Index 는 새 커밋으로 변환된다.

Working Directory

Working directory 는 일종의 Sandbox 로 생각하면 된다.

Branching

branching model

git에서의 브랜치 사용은, 단순한 명령어를 사용할 줄 아는 것보다 어떤 구조로 브랜치가 뻗어나가고, 통합되는지를 아는 것이 더 중요하다. 자동으로 생성되는 master branch 에는 Tag 와 같이 배포된 버전만을 관리하도록 한다. 그리고, develop branch 에는 현재 진행중인 모든 변경사항들이 적용될 수 있도록 한다. 그리고, 새로운 기능을 개발해야 하는 상황이라면 develop branch에서 새로운 branch 를 파생하여 개발하도록 한다(이건 약간 다를 수있다). hotfix 의 경우, master branch 에서 파생하여 수정 후, 바로 적용할 수 있도록 한다.

새로운 기능을 위한 branch 를 생성할 때, 두 가지 방식을 사용할 수 있다. 하나는 master branch 에서 파생하는 방법이고, 다른 하나는 develop branch 에서 파생하는 방법이다. develop branch 에서 파생할 경우에는 현재 적용을 위해 테스트 중인 모든 기능과의 호환성을 함께 테스트할 수 있지만 그만큼 현재 배포중인 버전과의 차이가 많이 난다는 문제가 있다. 하지만, master branch에서 파생하는 경우는, 정 반대의 문제가 발생하게 된다.

여기서 중요한 점은, branching 을 하는 과정에서는 어떠한 정해진 룰이 없다는 것이다. 그냥 각기 상황에 맞는 방식을 적용하여 사용하면 된다.

Commands

branch

branch 를 생성/삭제/변경 한다. <source lang=bash> $ git branch [--color[=<when>] | --no-color] [-r | -a] [--list] [-v [--abbrev=<length> | --no-abbrev]] [--column[=<options>] | --no-column] [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...] $ git branch [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>] $ git branch (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>] $ git branch --unset-upstream [<branchname>] $ git branch (-m | -M) [<oldbranch>] <newbranch> $ git branch (-d | -D) [-r] <branchname>... $ git branch --edit-description [<branchname>] </source>

git-2.16 버전부터 git branch 의 기본 동작 방식이 변경되었다. 마치 less 명령어와 같이 출력된다. 원래 설정으로 돌아가고 싶다면 pager.branch 설정을 false 로 설정하면 된다<ref>https://stackoverflow.com/questions/48341920/git-branch-command-behaves-like-less</ref>.

git config --global pager.branch false

-v, -vv, --verbose

Branch 상세 정보를 보여준다. <source lang=bash> $ git branch -vv

  • master e993892 [origin/master: ahead 2] Test change 2

</source>

-d, -D

지정된 Branch 를 삭제한다.

  • -d : Merge 가 완료된 Branch 를 삭제한다.
  • -D : Merge 여부와 상관없이 Branch 를 삭제한다.
$ git branch -D tmp
Deleted branch tmp (was 78e4777).

checkout

해당 브랜치 또는 특정 커밋시점으로 소스를 되돌린다. 아직 staging 에 있지 않은 파일에 checkout 을 적용하면 파일을 수정 전으로 되돌린다.

-b

브랜치 생성과 동시에 checkout 까지 동시에 한다. <source lang=bash> $ git checkout -b feature_1212 Switched to a new branch 'feature_1212' </source>

clean

Remove untracked files from the working tree.

Untracked file 들을 삭제한다.

-d

Remove untracked directories in addition to untracked files. If an untracked directory is managed by a different Git repository, it is not removed by default.

Use -f option twice if you really want to remove such a directory.

Untracked directory 와 디렉토리 안에 있는 파일들도 함께 삭제 한다.

$ git clean -fd
Removing playbooks/playbook_asterisk_deployment.yml

-f, --force

If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or directories unless given -f, -n or -i.

Git will refuse to delete directories with .git sub directory or file unless a second -f is given.

$ git clean -f
Removing ansible.cfg
Removing roles/asterisk/tasks/asterisk_deployment.yml

-n, --dry-run

Don't actually remove anythin, just show what would be done.

$ git clean -n
Would remove ansible.cfg
Would remove roles/asterisk/tasks/asterisk_deployment.yml

clone

-b, --branch

clone 시 특정 브랜치를 지정하여 clone 할 때 사용하는 옵션이다.

$ git clone -b <branch> <remote_repo>

Example
$ git clone -b my-branch git@github.com:user/myproject.git

Alternative (no public key setup needed):
$ git clone -b my-branch https://git@github.com/username/myproject.git

With Git 1.7.10 and later, add --single-branch to prevent fetching of all branches. Example, with OpenCV 2.4 branch:
$ git clone -b 2.4 --single-branch https://github.com/Itseez/opencv.git opencv-2.4

pull

pull all branches

$ git pull --all

push

현재 commit 의 내용을 remote 로 push 한다.

-u, --set-upstream

로컬 브랜치 내용을 remote 로 push 한다.

$ git push --set-upstream origin <local branch name>

--all 옵션과 같이 사용할 경우, 현재 로컬에 있는 모든 브랜치의 내용을 remote 로 push 한다.

$ git push --all -u

commit

--amend

기존의 commit 에 내용 수정하기

$ git commit --amend

rebase

Git에서 한 Branch 에서 다른 Branch 로 합치는 방법은 두 가지가 있다. 하나는 Merge 이고, 다른 하나는 Rebase 이다. Merge 가 소스를 통합하는 방식이라면, Rebase 는 다른 Branch 에서 변경된 사항을 패치(Patch)로 만들고, 이를 다시 본래의 Branch 에 적용시키는 방법이다. rebase 는 Branch 단위로만 가능하며, Commit 단위로는 불가능하다. rebase 를 위해서는 반드시 Branch 를 생성해야 한다<ref>http://stackoverflow.com/questions/7758128/how-to-git-rebase-i-for-a-range-of-commits</ref>.

git rebase [-i | --interactive] [options] [--onto <newbase>]
        <upstream> [<branch>]
git rebase [-i | --interactive] [options] --onto <newbase>
        --root [<branch>]

git rebase --continue | --skip | --abort
$ git checkout experiment
$ git rebase master

-i, --interactive

rebase 될 commit 의 리스트를 작성하고, 각각의 commit 에 대해 수행할 작업을 지정할 수 있는 interactive 모드를 시작한다. 보통은 commit 들을 합치고 싶을 때 가장 널리 사용되는 명령 중 하나이다.

$ git rebase -i HEAD~3

pick 23c7d18 Additional features
pick 3ba2192 Create billing database
pick 4caf479 - fix warns level for compiling client on freebsd..

# Rebase 1666596..4caf479 onto 1666596
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

사용가능한 Command 들의 각각의 기능은 다음과 같다.

  • p, pick : commit 된 내용을 그냥 그대로 사용한다.
  • r, reword : commit 된 내용을 그냥 그대로 사용한다. 단, commit 메시지를 수정한다.
  • e, edit : commit 된 내용을 그냥 그대로 사용한다. 단, 수정을 위해 잠시 정지(stop) 한다.
  • s, squash : commit 된 내용을 그냥 그대로 사용한다. 단, 여러개의 커밋들을 하나의 커밋으로 합친다.
  • f, fixup : squash 와 비슷하다. 단, commit message 는 사용하지 않는다.
  • x, exec : 쉘을 통한 command 를 실행한다.

squash 및 fixup 은 이전 커밋들을 대상으로만 수행할 수 있다. 최근 커밋을 이전 커밋으로 합하는 명령어가 아니기 때문이다. 그리고, 절대로 이미 push 했던 커밋을 대상으로는 rebase 해서는 안된다.

--abort

rebase 중 잘못 선택하거나 실수로 의도하는 것과 달라진 경우, 해당 rebase 를 취소하고자 할 때 사용하는 명령어이다. <source lang=bash> $ git rebase --abort </source>

--continue

rebase 중, merge 가 깨진 경우, 해당 파일을 수정 및 add 한 후, 계속해서 rebase 를 진행할 때 사용하는 명령어이다. <source lang=bash> $ git rebase --continue </source>

show-brarnch

브랜치와 커밋 내용을 확인한다.

$ git show-branch
[master] Oversized message cut and substitute

-a, --all

remote-tacking 브랜치와 로컬 브랜치 모두를 보여준다.

$ git show-branch -a
* [master] Oversized message cut and substitute
 ! [origin/HEAD] Oversized message cut and substitute
  ! [origin/develop] Oversized message cut and substitute
   ! [origin/master] Oversized message cut and substitute
----
*+++ [master] Oversized message cut and substitute

diff

Commit, Branch, Working 디렉토리 사이의 diff 를 나타낸다.

       git diff [options] [<commit>] [--] [<path>...]
       git diff [options] --cached [<commit>] [--] [<path>...]
       git diff [options] <commit> <commit> [--] [<path>...]
       git diff [options] <blob> <blob>
       git diff [options] [--no-index] [--] <path> <path>

Branch compare

Branch 끼리의 diff 를 보여준다.

$ git diff <branch 1> <branch 2>

$ git diff tmp tmp1
diff --git a//main.c b/main.c
index 237d99a..b54bca3 100644
--- a/main.c
+++ b/main.c
@@ -518,6 +518,90 @@ static bool validate_sms_table(const char* table_name, const char* attach_db)
     return true;
 }
...

HEAD

현재 파일들의 상태(아직 commit 되지 않은 상태의 변경도 포함)와 HEAD 와의 차이를 보여준다.

mv

파일, 심볼릭링크 또는 디렉토리의 이동 및 rename 을 한다. git 디렉토리에서 단순히 git 명령어가 아닌, unix/linux mv 명령어로 파일을 옮기게 되면 git 에서는 파일이동이 아닌, 파일 삭제, 새로운 파일 생성으로 받아들이게 된다.

만약 unix/linux 명령어 mv 로 파일이동을 하게 될 경우, 파일 트래킹 하기가 정말 어려워진다. git에서는 가급적 git mv를 사용하도록 하자.

-n, --dry-run

실제로 파일이동을 하지 않는다. 단지 어떻게 되는지만을 보여준다.

$ git mv -n conf/freeswitch.xml ./
Checking rename of 'conf/freeswitch.xml' to 'freeswitch.xml'
Renaming conf/freeswitch.xml to freeswitch.xml

reset

HEAD 가 가리키는 커밋을 변경한다.

       git reset [-q] [<tree-ish>] [--] <paths>...
       git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
       git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]

--mixed

Index 를 변경한다. 기본 동작방식이다.

--soft

Index 와 working directory 를 건드리지 않는다. 대신 HEAD 만을 이동한다.

--hard

Index 와 Working directory 를 변경한다. 즉, 로컬에 있는 모든 변경 내용과 확정본을 포기한다. 원격 저장소의 최신 이력을 가져오고, 로컬 master branch 가 해당 이력을 가리키도록 한다. <source lang=bash> $ git reset --hard origin/master HEAD is now at gba2192 test commit </source>

remote

현재 주시(track)중인 원격(remote) 저장소 내용들을 관리한다.

       git remote [-v | --verbose]
       git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
       git remote rename <old> <new>
       git remote rm <name>
       git remote set-head <name> (-a | -d | <branch>)
       git remote set-url [--push] <name> <newurl> [<oldurl>]
       git remote set-url --add [--push] <name> <newurl>
       git remote set-url --delete [--push] <name> <url>
       git remote [-v | --verbose] show [-n] <name>
       git remote prune [-n | --dry-run] <name>
       git remote [-v | --verbose] update [-p | --prune] [group | remote]...

set-url

Remote url 을 설정한다. pull/push 등을 하는 target url 을 변경한다. ssh/https 등의 접속 방식을 변경할 때 사용한다.

$ git remote -v
origin	git@github.com:pchero/jade-agent.git (fetch)
origin	git@github.com:pchero/jade-agent.git (push)

$ git remote set-url origin https://github.com/pchero/jade-agent.git
$ git remote -v
origin	https://github.com/pchero/jade-agent.git (fetch)
origin	https://github.com/pchero/jade-agent.git (push)

update

지정된 group 에 속한 원격 저장소 내용들을 update 한다. 만약 group 이 지정되어 있지 않다면, remotes.default 에 설정된 내용을 사용하게 된다. 만약 remotes.default 에 설정된 내용이 없다면, 전체 원격 저장소 내용들을 update 한다.

With --prune option, prune all the remotes that are updated.

$ git remote update
Fetching origin
remote: Counting objects: 18, done.
remote: Total 18 (delta 7), reused 7 (delta 7), pack-reused 11
Unpacking objects: 100% (18/18), done.
From https://github.com/pchero/asterisk-zmq
   2109230..9991691  master     -> origin/master
   2109230..43c3fbb  devel      -> origin/devel
 * [new tag]         v1.5       -> v1.5

fetch

원격 저장소의 변경 이력을 Download 한다. <source lang=bash> $ git fetch origin </source>

archive

log

Commit 이력을 확인한다. <source lang=bash> $ git log

commit 70b8a6e47475ed18d586be2e1625531981efdb18 Author: pchero <pchero@pchero21.com> Date: Mon Jun 20 10:47:28 2016 +0200

   Test change 2
   
   - Test change 2
   
   Change-Id: Id09dc1f32bb584678c6cdef2f2eb4fabd6756a09

commit 668cbd8f92c81d075d5619722713272484f065ce Author: pchero <pchero@pchero21.com> Date: Mon Jun 20 10:14:03 2016 +0200

   Test change commit 1
   
   - Test change commit 1
   - Test change again
   - Added Test change 1-1
   
   Change-Id: Ic13c9ec5d79cd682b5a4d4126e7acf6a9d16663a

</source>

config

git 환경변수 값을들 설정/변경/삭제 한다.

$ git config [options]

core.editor

default editor 를 설정한다.

$ git config --global core.editor vim

user.email

commit 시 사용되는 email address 를 설정한다.

$ git config --global user.email "pchero21@gmail.com"

user.name

commit 사 사용되는 user name 을 설정한다.

$ git config --global user.name "pchero"

--global

global config file 을 사용한다.

$ git config --global core.editor "vim"

Advanced

merge conflict

git merge conflict 발생 시 처리방법.

$ git merge
fatal: You have not concluded your merge (MERGE_HEAD exists).
Please, commit your changes before you can merge.

Errors

server certificate verification failed. CAfile

다음과 같은 에러가 있었다.

pchero@jenkins:~/git$ git clone https://lab.cluster.gsi.dit.upm.es/sefarad/sefarad.git
Cloning into 'sefarad'...
fatal: unable to access 'https://lab.cluster.gsi.dit.upm.es/sefarad/sefarad.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

SSL verify 옵션을 끄면된다.

export GIT_SSL_NO_VERIFY=1

error: unpack failed: error Missing tree

error: unpack failed: error Missing tree fa6b09d4f5dc8ee6fcb0553396530f97a3033856

다음과 같은 순서로 작업을 진행했을 경우 발생하는 에러이다.

- Create a new branch on head.
- Do some modifications on new branchs
- Somebody also make modifications on head branch
- Try to push your branch

git pull 진행 후, 다시 push 를 하면 된다.

See also

References

<references />