Home> ID PW Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)

Programming :::

git

설치

git | source tree

git 홈페이지 download에 가서 GUI clients를 클릭하면 다양한 GUI Clients에 대해 소개되어 있다.

https://git-scm.com/docs에 가면 모든 명령을 확인할 수 있다.

https://git-scm.com/book/ko/에 가면 입문자를 위한 한글문서를 볼 수 있다.

https://github.com/github/gitignore에 가면 .gitignore 템플릿 파일들을 다운받을 수 있다.

git 버전확인

$ git --version

git 환경설정확인

$ git config --list

git을 설치하게 되면 git의 환경설정이 .gitconfig 파일에 저장된다.

.gitconfig 파일 내용보는 명령

기본 편집기(=vi)로 열기

$ git config --global -e

vscode로 열기

$ git config --global core.editor "code"
$ git config --global core.editor "code --wait"

위와같이 code에 --wait 옵션을 주면, vscode가 종료될 때까지 shell이 대기한다.

user 설정

$ git config --global user.name "namu4s"
$ git config --global user.email "namu4g@gmail.com"

user 설정 확인

$ git config user.name
$ git config user.email

autocrlf 설정 - Windows -> ture, Mac -> input

$ git config --global core.autocrlf true
$ git config --global core.autocrlf intput

core.autocrlf 설정하면,

- Windows: \r\n (carriage-return, line feed)

  * Windows에서 git에 넣을 땐 자동으로 \r을 빼고, git에서 꺼내올 땐 자동으로 \r을 붙인다.

- Mac: \n (line feed)

  * Mac에서 git에 넣을 땐 자동으로 \r을 빼고, git에서 꺼내올 땐 그냥 꺼내온다.

폴더안에서 git init 수행하면, .git 폴더 생성됨

폴더안에서 rm -rf .git 해서 삭제하면 git repository 제거됨

git 상태 보기

$ git status

alias

$ git config --global alias.st status
$ git st

해당 명령 도움말 보기

$ git config --h

git workflow

git의 3가지 작업환경
$ echo hello world! > a.txt
$ echo hello world! > b.txt
$ echo hello world! > c.txt
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add ..." to include in what will be committed)
        a.txt
        b.txt
        c.txt

nothing added to commit but untracked files present (use "git add" to track)

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ 
$ git add a.txt
warning: LF will be replaced by CRLF in a.txt.
The file will have its original line endings in your working directory

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   a.txt

Untracked files:
  (use "git add ..." to include in what will be committed)
        b.txt
        c.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

모든 txt 파일을 add한다. add된 시점에 staging area로 옮겨지며, tracking 되기 시작한다.

$ git add *.txt

a.txt 파일을 수정하고, git status 해보면, modifed에도 a.txt가 있다.

$ echo hi~ >> a.txt

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt

Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        modified:   a.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$


이 상태에서 git rm --cached * 하면 error가 발생한다.

$ git rm --cached *
error: the following file has staged content different from both the
file and the HEAD:
    a.txt
(use -f to force removal)

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ 

modified 된 a.txt도 다시 한번 add 해준다.

$ git add a.txt
warning: LF will be replaced by CRLF in a.txt.
The file will have its original line endings in your working directory

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

이제 모두 staging area에 있으므로 git rm --cached * 할 수 있다.

$ git rm --cached *
rm 'a.txt'
rm 'b.txt'
rm 'c.txt'

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add ..." to include in what will be committed)
        a.txt
        b.txt
        c.txt

nothing added to commit but untracked files present (use "git add" to track)

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

이제 다시 모두 add한 후, 이번에는 a.txt를 삭제해보자.

$ git add *
warning: LF will be replaced by CRLF in a.txt.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in b.txt.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in c.txt.
The file will have its original line endings in your working directory

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ rm a.txt

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ ls
b.txt  c.txt

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt

Changes not staged for commit:
  (use "git add/rm ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        deleted:    a.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

이 상태에서는 add *를 해도 삭제된 a.txt가 돌아오진 않기 때문에 기존 상태가 유지된다.

$ git add *

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt

Changes not staged for commit:
  (use "git add/rm ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        deleted:    a.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

여기서 git add . 을 입력하면, staging area에서도 a.txt가 삭제되어 정리된다.

여기서 . 은 현재 디렉토리를 가리키며, git add로 디렉토리를 지정할 경우, 디렉토리의 현재 상태와 일치하도록 index(=staging area)를 업데이트 합니다. 즉, 신규파일은 추가되고, 삭제된 파일은 staging area에서도 삭제됩니다. 단, ignored 파일들은 추가되지 않습니다.

$ git add .

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   b.txt
        new file:   c.txt


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

git status

Changes to be committed: 이 영역은 스테이징 영역에 넘어가 있는 변경 내용을 보여줍니다. Changes not staged for commit: 이 영역은 아직 워킹 디렉토리에 있는 변경 내용을 보여줍니다. Untracked files: 이 영역도 아직 워킹 디렉토리에 있는 아직 한 번도 해당 Git 저장소가 관리한 적이 없는 새로운 파일을 보여줍니다.

git add

$git add 파일 또는 디렉토리. wildcard character 사용가능하며, 디렉토리 지정 시, 하위 디렉토리를 포함함.
$git add . : .은 현재 디렉토리를 의미하며, 현재 디렉토리와 하위디렉토리를 포함한 전체 목록과 동일하게 index를 업데이트 한다.(=staging area 에 반영한다.)
    즉, working directory에서 삭제되었지만, staging area에 아직 반영되지 않은 파일은 삭제되고,
    신규 생성한 파일은 추가된다.
$git add -A : 작업 디렉토리 상에 어디에 위치하든 항상 동일하게 모든 변경 내용을 스테이징으로 넘깁니다.
$git add -p : 각 변경 사항을 터미널에서 하나씩 확인하면서 스테이징 영역으로 넘기거나 또는 제외할 수가 있다.

ignored files

$ echo lll > log.log

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ echo *.log > .gitignore

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ cat .gitignore
log.log

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ ls -alF
total 13
drwxr-xr-x 1 namu4 197609  0 Sep 23 21:21 ./
drwxr-xr-x 1 namu4 197609  0 Sep 23 17:06 ../
drwxr-xr-x 1 namu4 197609  0 Sep 23 20:58 .git/
-rw-r--r-- 1 namu4 197609  8 Sep 23 21:21 .gitignore
-rw-r--r-- 1 namu4 197609 13 Sep 23 18:14 b.txt
-rw-r--r-- 1 namu4 197609 13 Sep 23 18:14 c.txt
-rw-r--r-- 1 namu4 197609  4 Sep 23 20:33 d.txt
-rw-r--r-- 1 namu4 197609  4 Sep 23 21:17 log.log

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   b.txt
        new file:   c.txt
        new file:   d.txt

Untracked files:
  (use "git add ..." to include in what will be committed)
        .gitignore


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

.gitignore 파일은 추가되어 Untracked files에 나오지만, log.log 파일은 보이지 않는다.

vi .gitignore 를 실행해서, 무시할 파일들을 Fileglobs로 지정할 수 있다.

*.log
build/
build/*.log

기본예시는 https://github.com/github/gitignore 를 참조하라.

.gitignore 는 표준 Glob를 사용하고 몇가지 패턴이 있다.

# : comment
* : 와일드 카드
! : 무시를 무시
!go.txt : *.txt로 txt 파일은 무시하기로 했지만, 이 규칙을 무시하고 go.txt는 staged에 올린다.
/ : path 표시
/module : 루트 디렉터리 아래 /module 파일을 무시. 그러나, user/module은 무시되지 않는다.
js/ : js 디렉토리 아래 모든 파일 무시
css/*.txt : css 디렉토리 아래 확장자가 txt를 모두 무시

git status 자세히 알아보기

$ git status -h
usage: git status [<options>] [--] <pathspec>...

    -v, --verbose         be verbose
    -s, --short           show status concisely
    -b, --branch          show branch information
    --show-stash          show stash information
    --ahead-behind        compute full ahead/behind values
    --porcelain[=<version>]
                          machine-readable output
    --long                show status in long format (default)
    -z, --null            terminate entries with NUL
    -u, --untracked-files[=<mode>]
                          show untracked files, optional modes: all, normal, no. (Default: all)
    --ignored[=<mode>]    show ignored files, optional modes: traditional, matching, no. (Default: traditional)
    --ignore-submodules[=<when>]
                          ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)
    --column[=<style>]    list untracked files in columns
    --no-renames          do not detect renames
    -M, --find-renames[=<n>]
                          detect renames, optionally set similarity index
    --show-ignored-directory
                          (DEPRECATED: use --ignore=matching instead) Only show directories that match an ignore pattern name.
    --no-lock-index       (DEPRECATED: use `git --no-optional-locks status` instead) Do not lock the index


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

defalut는 --long 옵션이 적용된다. -s, --short은 간단하게 보여줌. -b, --branch 브랜치 관련 정보 확인.

$ git status -s
A  b.txt
A  c.txt
A  d.txt
?? .gitignore

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ vi d.txt

..... 여기서 d.txt 파일 수정함 ....

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git status -b -s
## No commits yet on master
A  b.txt
A  c.txt
AM d.txt
?? .gitignore

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ 

A : staging area에 추가(Add)된 파일
AM : staging area에 추가된 후, 수정(Modify)된 파일
?? : 아직 tracking 되지 않은 working directory에만 있는 파일들

git diff : working directory와 staging area의 파일 비교

$ git diff
warning: LF will be replaced by CRLF in d.txt.
The file will have its original line endings in your working directory
diff --git a/d.txt b/d.txt
index 63aefe1..aa28223 100644
--- a/d.txt
+++ b/d.txt
@@ -1 +1,2 @@
 kkk
+jjj

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

git diff --staged : staging area와 .git directory의 파일 비교

$ git diff --staged
diff --git a/b.txt b/b.txt
new file mode 100644
index 0000000..a042389
--- /dev/null
+++ b/b.txt
@@ -0,0 +1 @@
+hello world!
diff --git a/c.txt b/c.txt
new file mode 100644
index 0000000..a042389
--- /dev/null
+++ b/c.txt
@@ -0,0 +1 @@
+hello world!
diff --git a/d.txt b/d.txt
new file mode 100644
index 0000000..63aefe1
--- /dev/null
+++ b/d.txt
@@ -0,0 +1 @@
+kkk

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

git diff -h 해보면 --cached 가 나오는데, --staged와 같은 의미이다.

$ git diff -h
usage: git diff [] [] [--] [...]
   or: git diff [] --cached [] [--] [...]
   or: git diff []  [--merge-base] [...]  [--] [...]
   or: git diff [] ...] [--] [...]
   or: git diff []  ]
   or: git diff [] --no-index [--]  ]

common diff options:
  -z            output diff-raw with lines terminated with NUL.
  -p            output patch format.
  -u            synonym for -p.
  --patch-with-raw
                output both a patch and the diff-raw format.
  --stat        show diffstat instead of patch.
  --numstat     show numeric diffstat instead of patch.
  --patch-with-stat
                output a patch and prepend its diffstat.
  --name-only   show only names of changed files.
  --name-status show names and status of changed files.
  --full-index  show full object name on index lines.
  --abbrev=  abbreviate object names in diff-tree header and diff-raw.
  -R            swap input file pairs.
  -B            detect complete rewrites.
  -M            detect renames.
  -C            detect copies.
  --find-copies-harder
                try unchanged files as candidate for copy detection.
  -l         limit rename attempts up to  paths.
  -O      reorder diffs according to the .
  -S    find filepair whose only one side contains the string.
  --pickaxe-all
                show all files diff when -S is used and hit is found.
  -a  --text    treat all files as text.


namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

git config --global -e : global로 설정되어 있는 config를 edit하기

$ git config --global -e

아래와 같이 diff와 difftool을 추가하면, vscode로 비교한다.

... 생략 ...
[diff]
	tool = vscode
[difftool "vscode"]
	cmd = code --wait --diff $LOCAL $REMOTE

diff 툴은 vscode를 사용하고, 명령은 vscode 실행파일인 code(=code.exe)와 그 뒤에 오는 인자들로 구성된다는 뜻.

$ git difftool
warning: LF will be replaced by CRLF in d.txt.
The file will have its original line endings in your working directory

Viewing (1/1): 'd.txt'
Launch 'bc' [Y/n]?

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git difftool --staged

Viewing (1/3): 'b.txt'
Launch 'bc' [Y/n]?

Viewing (2/3): 'c.txt'
Launch 'bc' [Y/n]?

Viewing (3/3): 'd.txt'
Launch 'bc' [Y/n]? n

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$

git commit

git commit을 실행하면, 편집기가 실행되고, 첫줄에 타이틀, 둘째줄부터 좀더 자세한 설명을 작성한 후, 저장하고 나오면, commit됨.

$ git add .
warning: LF will be replaced by CRLF in d.txt.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in .gitignore.
The file will have its original line endings in your working directory

$ git commit
[master (root-commit) c503cc4] Test Title 그냥 작성해봅니다.
 4 files changed, 7 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 b.txt
 create mode 100644 c.txt
 create mode 100644 d.txt

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$ git log
commit c503cc4170b171dc5b41595b60bfc5d0f848fc05 (HEAD -> master)
Author: namu4s <namu4g@gamil.com>
Date:   Thu Sep 23 22:39:01 2021 +0900

    Test Title
    그냥 작성해봅니다.

namu4@BLACKROSE MINGW64 /c/data/ws/git/Study/git_study/test/tt (master)
$
$ echo add >> c.txt
$ git status -s

$ git add .
$ git commit -m "second commit"

$ echo add >> c.txt
$ git commit -a -m  "third commit"
$ git commit -am  "third commit"

파일전체를 staging area에 반영하거나, 반영된 내용을 제거하는 방법도 있지만, 수정된 라인만 골라서 반영하거나 제거할 수도 있다.


stage lines 버튼 선택하면, 선택된 라인만 staging area에 반영된다.



$ 

stage lines 버튼을 눌러 옮길 것은 1라인뿐만 아니라, 라인 범위로 여러 라인을 옮길 수도 있다.
단, 연속되지 않은 구간은 한번에 옮길 수 없다.
하지만 연속된 구간단위 옮기기를 반복하면, 원하는 구간만 라인단위로 골라서 옮기는 것도 가능하다.

alias 설정예.. 근데 영상에서 오른쪽 부분이 좀 짤렸다.

[alias]
	s = status
	l = log --graph --all -pretty=format:'%C(yellow)%h%C(cyan)'	// 일부짤림
	up = !git fetch origin master && git rebase 
	co = checkout
	ca = !git add -A && git commit -m
	cad = !git add -A && git commit -m "."
	c = commitsb = brance
	list = stash list
	smudge = git-lfs smudge -- %f
	process = git-lfs filter-process
	required = ture
[pull]	
	rebase = false
■ tortoise git에서 commit 순서 바꾸기 (rebase)
1) show log 선택 후, log 목록에서 순서변경 대상보다 하나더 이전항목을 마우스 우측 클릭 후, Rebase "master" onto this...(G) 메뉴 선택.


2) Force Rebase 체크해서 목록이 나오면, 순서변경할 항목 선택 후, Up / Down 버튼 클릭해서 순서바꾸고, Start Rebase 클릭.
3) 충돌 발생 시엔???

* 자주쓰면 명령 ■ pull origin을 master에 pull하면서 submodule 이 포함된 것까지 같이 pull한다. $ git pull origin master --recurse-submodules $ git --help $ git help -a $ git help -g $ git help pull --> 웹브라우저로 pull command에 대한 매뉴얼 페이지를 열어줌
namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git status On branch branch_new Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: sub_module_test.txt no changes added to commit (use "git add" and/or "git commit -a") namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git status -s M sub_module_test.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ //////// test2.txt 파일 추가 생성 후, //////// namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git status -s M sub_module_test.txt ?? test2.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git add *.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git status -s M sub_module_test.txt A test2.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git commit -m 'branch_new test' [branch_new ac8a09b] branch_new test 2 files changed, 3 insertions(+) create mode 100644 test2.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $
2.1 Git의 기초 - Git 저장소 만들기 ▨ Git 저장소 만들기 $ git init 이 명령은 .git 이라는 하위 디렉토리를 만든다. .git 디렉토리에는 저장소에 필요한 뼈대 파일(Skeleton)이 들어 있다. 이 명령만으로는 아직 프로젝트의 어떤 파일도 관리하지 않는다. (.git 디렉토리가 막 만들어진 직후에 정확히 어떤 파일이 있는지에 대한 내용은 Git의 내부에서 다룬다) Git이 파일을 관리하게 하려면 저장소에 파일을 추가하고 커밋해야 한다. git add 명령으로 파일을 추가하고 git commit 명령으로 커밋한다: $ git add *.c $ git add LICENSE $ git commit -m 'initial project version' ■ 기존 디렉토리를 Git 저장소로 만들기 $ git init .git 디렉토리가 생성되며, 저장소가 만들어짐. ■ 기존 저장소를 Clone 하기 $ git clone https://github.com/libgit2/libgit2 --> libgit2 폴더에 클론 생성됨 $ git clone https://github.com/libgit2/libgit2 mylibgit --> mylibgit 폴더에 클론 생성됨
2.2 Git의 기초 - 수정하고 저장소에 저장하기 $ git add README 이 명령을 통해 디렉토리에 있는 파일을 추적하고 관리하도록 한다. git add 명령은 파일 또는 디렉토리의 경로를 아규먼트로 받는다. 디렉토리면 아래에 있는 모든 파일들까지 재귀적으로 추가한다. ■ .gitignore .gitignore 파일에 입력하는 패턴은 아래 규칙을 따른다. - 아무것도 없는 라인이나, `#`로 시작하는 라인은 무시한다. - 표준 Glob 패턴을 사용한다. 이는 프로젝트 전체에 적용된다. - 슬래시(/)로 시작하면 하위 디렉토리에 적용되지(Recursivity) 않는다. - 디렉토리는 슬래시(/)를 끝에 사용하는 것으로 표현한다. - 느낌표(!)로 시작하는 패턴의 파일은 무시하지 않는다. Glob 패턴은 정규표현식을 단순하게 만든 것으로 생각하면 되고 보통 쉘에서 많이 사용한다. 애스터리스크(*)는 문자가 하나도 없거나 하나 이상을 의미하고, [abc] 는 중괄호 안에 있는 문자 중 하나를 의미한다(그러니까 이 경우에는 a, b, c). 물음표(?)는 문자 하나를 말하고, [0-9] 처럼 중괄호 안의 캐릭터 사이에 하이픈(-)을 사용하면 그 캐릭터 사이에 있는 문자 하나를 말한다. 애스터리스크 2개를 사용하여 디렉토리 안의 디렉토리 까지 지정할 수 있다. a/**/z 패턴은 a/z, a/b/z, a/b/c/z 디렉토리에 사용할 수 있다. 아래는 .gitignore 파일의 예이다. # 확장자가 .a인 파일 무시 *.a # 윗 라인에서 확장자가 .a인 파일은 무시하게 했지만 lib.a는 무시하지 않음 !lib.a # 현재 디렉토리에 있는 TODO파일은 무시하고 subdir/TODO처럼 하위디렉토리에 있는 파일은 무시하지 않음 /TODO # build/ 디렉토리에 있는 모든 파일은 무시 build/ # doc/notes.txt 파일은 무시하고 doc/server/arch.txt 파일은 무시하지 않음 doc/*.txt # doc 디렉토리 아래의 모든 .pdf 파일을 무시 doc/**/*.pdf Hint GitHub은 다양한 프로젝트에서 자주 사용하는 .gitignore 예제를 관리하고 있다. 어떤 내용을 넣을지 막막하다면 https://github.com/github/gitignore 사이트에서 적당한 예제를 찾을 수 있다. Note .gitignore`를 사용하는 간단한 방식은 하나의 `.gitignore 파일을 최상위 디렉토리에 하나 두고 모든 하위 디렉토리에까지 적용시키는 방식이다. 물론 .gitignore 파일을 하나만 두는 것이 아니라 하위 디렉토리에도 추가로 둘 수도 있다. .gitignore 정책은 현재 .gitignore 파일이 위치한 디렉토리와 그 하위 디렉토리에 적용된다. (리눅스 커널 소스 저장소에는 .gitignore 파일이 206개나 있음) 다수의 .gitignore 파일을 두고 정책을 적용하는 부분은 이 책에서 다루는 범위를 벗어난다. 자세한 내용은 `man gitignore`에서 확인할 수 있다. ■ git diff - git diff 명령은 마지막으로 커밋한 후에 수정한 것들 전부를 보여주지 않는다. git diff 는 Unstaged 상태인 것들만 보여준다. - Staged 상태인 파일은 git diff --cached 옵션으로 확인한다. --staged 와 --cached 는 같은 옵션이다. 외부 도구로 비교하기 Note 이 책에서는 계속 git diff 명령으로 여기저기서 써 먹는다. 즐겨 쓰거나 결과를 아름답게 보여주는 Diff 도구가 있으면 사용할 수 있다. git diff 대신 git difftool 명령을 사용해서 emerge, vimdiff 같은 도구로 비교할 수 있다. 상용 제품도 사용할 수 있다. git difftool --tool-help 라는 명령은 사용가능한 도구를 보여준다. namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git status -s M test2.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git diff warning: LF will be replaced by CRLF in test2.txt. The file will have its original line endings in your working directory diff --git a/test2.txt b/test2.txt index f2ba8f8..8a81316 100644 --- a/test2.txt +++ b/test2.txt @@ -1 +1,5 @@ -abc \ No newline at end of file +abc +추가수정을 해보자. + +comit 두번하기. + namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git diff --staged //// modify된 것은 있지만, stage 된것은 없기에 아무것도 보여주지 않는다. namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git add test2.txt warning: LF will be replaced by CRLF in test2.txt. The file will have its original line endings in your working directory namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git status -s M test2.txt namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git diff //// add 명령으로 모두 stage에 추가되었기에, 아무것도 보여주지 않는다. namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git diff --staged diff --git a/test2.txt b/test2.txt index f2ba8f8..8a81316 100644 --- a/test2.txt +++ b/test2.txt @@ -1 +1,5 @@ -abc \ No newline at end of file +abc +추가수정을 해보자. + +comit 두번하기. + namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ //// 수정된 것 말고, stage에 추가된 것만 보여준다. //// Stage 한 후에 다시 수정해도 git diff 명령을 사용할 수 있다. 이때는 Staged 상태인 것과 Unstaged 상태인 것을 비교한다. $ git difftool $ git difftool --tool-help ■ stage 추가와 commit을 한번에 하기 $ git commit -a -m 'added new benchmarks' $ git rm Tracked 상태의 파일을 삭제한 후에(정확하게는 Staging Area에서 삭제하는 것) 커밋해야 한다. 이 명령은 워킹 디렉토리에 있는 파일도 삭제하기 때문에 실제로 파일도 지워진다. $ git rm -f 이미 파일을 수정했거나 Staging Area에(역주 - Git Index라고도 부른다) 추가했다면 -f 옵션을 주어 강제로 삭제해야 한다. $ git rm --cached README Staging Area에서만 제거하고 워킹 디렉토리에 있는 파일은 지우지 않고 남겨둘 수 있다. 다시 말해서 하드디스크에 있는 파일은 그대로 두고 Git만 추적하지 않게 한다. $ git rm log/\*.log log/*.log 파일을 지우려면, *를 그냥 쓰면 정규식으로인식하므로, \*로 써야 지워진다. $ git rm \*~ ~로 끝나는 모든 파일 삭제 ■ 파일 이름 변경하기 Git은 파일 이름의 변경이나 파일의 이동을 명시적으로 관리하지 않는다. 굳이 파일 이름이 변경되었다는 것을 추적하지 않아도 아는 방법이 있다. $ git mv file_from file_to git mv 명령은 일종의 단축 명령어이다. 사실 git mv 명령은 아래 명령어를 수행한 것과 완전 똑같다. $ mv README.md README $ git rm README.md $ git add README
2.3 Git의 기초 - 커밋 히스토리 조회하기 2.4 Git의 기초 - 되돌리기 커밋을 했는데 Stage 하는 것을 깜빡하고 빠트린 파일이 있으면 아래와 같이 고칠 수 있다. $ git commit -m 'initial commit' $ git add forgotten_file $ git commit --amend 여기서 실행한 명령어 3개는 모두 커밋 한 개로 기록된다. 두 번째 커밋은 첫 번째 커밋을 덮어쓴다. Note 이렇게 --amend 옵션으로 커밋을 고치는 작업은, 추가로 작업한 일이 작다고 하더라도 이전의 커밋을 완전히 새로 고쳐서 새 커밋으로 변경하는 것을 의미한다. 이전의 커밋은 일어나지 않은 일이 되는 것이고 당연히 히스토리에도 남지 않는다. --amend 옵션으로 커밋을 고치는 작업이 주는 장점은 마지막 커밋 작업에서 아주 살짝 뭔가 빠뜨린 것을 넣거나 변경하는 것을 새 커밋으로 분리하지 않고 하나의 커밋에서 처리하는 것이다. “앗차, 빠진 파일 넣었음”, “이전 커밋에서 오타 살짝 고침” 등의 커밋을 만들지 않겠다는 말이다. ■ 파일 상태를 Unstage로 변경하기 $ git reset HEAD Staging Area에 있는 것을 Unstaged 상태로 변경한다. Note git reset 명령은 매우 위험하다. --hard 옵션과 함께 사용하면 더욱 위험하다. 하지만 위에서 처럼 옵션 없이 사용하면 워킹 디렉토리의 파일은 건드리지 않는다. reset 명령이 정확히는 어떻게 동작하는지, 어떻게 전문적으로 활용하는지는 Reset 명확히 알고 가기(https://git-scm.com/book/ko/v2/ch00/_git_reset) 부분에서 자세히 살펴보기로 한다. ■ Modified 파일 되돌리기 $ git checkout -- 중요(Important) git checkout — [file] 명령은 꽤 위험한 명령이라는 것을 알아야 한다. 원래 파일로 덮어썼기 때문에 수정한 내용은 전부 사라진다. 수정한 내용이 진짜 마음에 들지 않을 때만 사용하자. 변경한 내용을 쉽게 버릴수는 없고 하지만 당장은 되돌려야만 하는 상황이라면 Stash와 Branch를 사용하자. Git 브랜치 에서 다루는 이 방법들이 훨씬 낫다.
2.5 Git의 기초 - 리모트 저장소 namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git remote origin namu4@Sirius MINGW64 /d/data/ws/git/Study/git_study/test/second_pjt (branch_new) $ git remote -v origin https://gitlab.kanglab.com:8090/namu4s/second_pjt.git (fetch) origin https://gitlab.kanglab.com:8090/namu4s/second_pjt.git (push) ■ 리모트 저장소 추가하기 (Adding Remote Repositories) 기존 워킹 디렉토리에 새 리모트 저장소를 추가하는 명령 git remote add <단축이름> $ git remote origin $ git remote add pb https://github.com/paulboone/ticgit $ git remote -v origin https://github.com/schacon/ticgit (fetch) origin https://github.com/schacon/ticgit (push) pb https://github.com/paulboone/ticgit (fetch) pb https://github.com/paulboone/ticgit (push) 이제 URL 대신에 pb 라는 이름을 사용할 수 있다. ■ 리모트 저장소를 Pull 하거나 Fetch 하기 (Fetching and Pulling from Your Remotes) $ git fetch merge는 하지 않고, remote의 내용을 local에 가져오기만 한다. ■ 리모트 저장소에 Push 하기 (Pushing to Your Remotes) $ git push origin master ■ 리모트 저장소 살펴보기 (Inspecting a Remote) git remote show <리모트 저장소 이름> 명령으로 리모트 저장소의 구체적인 정보를 확인할 수 있다. origin 같은 단축이름으로 이 명령을 실행하면 아래와 같은 정보를 볼 수 있다. $ git remote show origin * remote origin Fetch URL: https://github.com/schacon/ticgit Push URL: https://github.com/schacon/ticgit HEAD branch: master Remote branches: master tracked dev-branch tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) 리모트 저장소의 URL과 추적하는 브랜치를 출력한다. 이 명령은 git pull 명령을 실행할 때 master 브랜치와 Merge 할 브랜치가 무엇인지 보여 준다. git pull 명령은 리모트 저장소 브랜치의 데이터를 모두 가져오고 나서 자동으로 Merge 할 것이다. 그리고 가져온 모든 리모트 저장소 정보도 출력한다. ■ 리모트 저장소 이름을 바꾸거나 리모트 저장소를 삭제하기 $ git remote rename pb paul $ git remote origin paul $ git remote remove paul $ git remote origin
■ 로컬에서 만든 branch를 remote에 push 하기 # 로컬 branch branch_new 생성 $ git checkout -b branch_new # branch_new에 대한 remote 정보가 미설정되어 있어 실패함 $ git push origin branch_new # 아래와 같이 업스트림 설정과 동시에 푸시하면 성공 $ git push --set-upstream origin branch_new # 아니면, 아래와 같이 업스트림을 먼저 설정하고, push 해도 됨 $ git branch --set-upstream-to origin/branch_new $ git push
■ 기존 버전관리 시스템과 Git의 차이 - 델타 기반 버전관리 시스템 : CVS, Subverson, ... : 각 파일의 변화를 시간순으로 관리하면서 파일들의 집합을 관리한다(보통 이라 함). - Git : 데이터를 파일 시스템 스냅샷의 연속으로 취급하고 크기가 아주 작다. Git은 커밋하거나 프로젝트의 상태를 저장할 때마다 파일이 존재하는 그 순간을 중요하게 여긴다. 파일이 달라지지 않았으면 Git은 성능을 위해서 파일을 새로 저장하지 않는다. 단지 이전 상태의 파일에 대한 링크만 저장한다. Git은 데이터를 스냅샷의 스트림처럼 취급한다. Git은 강력한 도구를 지원하는 작은 파일시스템이다. ■ Git의 브랜치 : Git의 브랜치는 커밋 사이를 가볍게 이동할 수 있는 어떤 포인터 같은 것이다. 기본적으로 Git은 master 브랜치를 만든다. 처음 커밋하면 이 master 브랜치가 생성된 커밋을 가리킨다. 이후 커밋을 만들면 master 브랜치는 자동으로 가장 마지막 커밋을 가리킨다. git branch 명령으로 testing 브랜치를 만든다. $ git branch testing 새로 만든 브랜치도 지금 작업하고 있던 마지막 커밋을 가리킨다. 한 커밋 히스토리(=스냅샷)를 가리키는 두 브랜치가 생긴 것이다. 지금 작업 중인 브랜치가 무엇인지 Git은 어떻게 파악할까. 'HEAD’라는 특수한 포인터가 있다. 이 포인터는 지금 작업하는 로컬 브랜치를 가리킨다. testing이라는 브랜치를 새로 만들었지만, Git은 아직 master 브랜치를 가리키고 있다. git branch 명령은 브랜치를 만들기만 하고 브랜치를 옮기지 않는다. $ git checkout testing 이렇게 하면 HEAD는 testing 브랜치를 가리킨다. 여러 브렌치 중 현재 작업중인 브렌치를 가리키는 포인터이므로, 하나뿐이다. 수정후, Commit하면, Brench도 생성된 커밋을 가리키고, Head도 같이 새로 생성된 커밋을 가리킨다. 실제로 Git의 브랜치는 어떤 한 커밋을 가리키는 40글자의 SHA-1 체크섬 파일에 불과하기 때문에 만들기도 쉽고 지우기도 쉽다. 새로 브랜치를 하나 만드는 것은 41바이트 크기의 파일을(40자와 줄 바꿈 문자) 하나 만드는 것에 불과하다. 이슈 관리 시스템에 등록된 53번 이슈를 처리한다고 하면 이 이슈에 집중할 수 있는 브랜치를 새로 하나 만든다. 브랜치를 만들면서 Checkout까지 한 번에 하려면 git checkout 명령에 -b 라는 옵션을 추가한다. $ git checkout -b iss53 Switched to a new branch "iss53" 위 명령은 아래 명령을 줄여놓은 것이다. $ git branch iss53 $ git checkout iss53 브랜치를 이동하려면 해야 할 일이 있다. 아직 커밋하지 않은 파일이 Checkout 할 브랜치와 충돌 나면 브랜치를 변경할 수 없다. 브랜치를 변경할 때는 워킹 디렉토리를 정리하는 것이 좋다. 이런 문제를 다루는 방법은(주로, Stash이나 커밋 Amend에 대해) 나중에 Stashing과 Cleaning 에서 다룰 것이다. 지금은 작업하던 것을 모두 커밋하고 master 브랜치로 옮긴다: $ git checkout master Switched to branch 'master'