[Git] 깃(Git) 핵심 사용법 총정리: 기초(add, commit, push)부터 브랜치(branch, merge)와 되돌리기(reset, revert)까지
1. Git 기초와 로컬 작업 흐름
1. Git 초기 설정
커밋 작성자(author) 설정
- 최초 1회 설정
- 만약 설정을 하지 않고 진행하면 commit 메시지를 남기는 상황에서 아래와 같은 에러 발생
$ git commit -m "Initial commit"
Author identity unknown # 이거 누가 쓴지 모르겠다는 의미
*** Please tell me who you are. # 님이 누군지 좀 알려줘..!
Run # 아래 이거 그냥 따라하셈
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'poeun@DESKTOP-21K4HL.(none)')
- 이 설정은 인증(로그인) 정보와는 전혀 상관없음
author 설정
$ git config --global user.email "rjsdudans@naver.com"
$ git config --global user.name "ingu627"
설정 확인
$ git config --global --list # -l(소문자)
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
filter.lfs.clean=git-lfs clean -- %f
user.name=ingu627
user.email=rjsdudans@naver.com
init.defaultbranch=master
(추가 설정) 커밋 편집기 변경
-
해당 명령어는 반드시 vscode가 설치되어 있어야 함
-
기본 텍스트 편집기를
vim에서vscode로 변경하는 것
$ git config --global core.editor "code --wait"
로컬 저장소의 git 히스토리 삭제
$ rm -rf .git
2. 파일 생성
폴더 생성
$ mkdir 폴더명
파일 생성
$ touch 파일명
파일 열기
$ vi 파일명
3. Git Basic
로컬 저장소 설정
# git 초기화 -> master 표시가 뜰 것!
# 결과적으로 해당 폴더에 숨기 폴더로 .git/이라는 폴더가 생김
$ git init
Initialized empty Git repository in F:/test/.git/
$ touch a.txt # a.txt 파일 생성
$ touch b.txt # b.txt 파일 생성
로컬 저장소의 git 삭제할 때
$ rm -rf .git
확인
$ ls -a
./ ../ .git/ a.txt b.txt
- a.txt와 b.txt를 touch로 만들어 놨다.
주의 사항!!
.git폴더가 또 다른 폴더 내부에 있으면 안됨! (git 속 git은 절대 금지!!!)

status
현재 git이 관리하는 폴더의 파일과 폴더 상태를 알려주는 명령어(working directory & staging area를 확인하는 명령어)
$ git status # WD & SA를 확인하는 명령어!! 정말 정말 중요하기 때문에 습관적으로 사용해야 한다.
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
a.txt
b.txt
nothing added to commit but untracked files present (use "git add" to track)
add
WD -> SA로 올리는 과정
$ git add a.txt
$ git status
On branch master
No commits yet
Changes to be committed: # 커밋 되어질 변경 사항들
(use "git rm --cached <file>..." to unstage)
new file: a.txt
Untracked files: # git이 아직 변경 사항을 추적하고 있지 않은 친구들
(use "git add <file>..." to include in what will be committed)
b.txt

# 기본 -> commit을 위한 폴더 & 파일을 추가!
$ git add 파일/폴더이름
$ git add a.txt # 특정 파일을 WD -> SA
$ git add . # 해당 디렉토리(하위 디렉토리 모두 포함)의 모든 폴더 & 파일을 SA
$ git add my-folder/ # 특정 디렉토리를 WD -> SA
윈도우 git 에서 한글 파일이 깨져 나올 때 해결 방법
$ git config core.quotepath false
터미널 입력 시 파일명에 공백이 있을 경우 문제
- 터미널에서 명렁어 입력 시 파일명, 폴더명에 공백이 있으면 제대로 인식이 안된다. 이럴 때는 공백 앞에 역슬래시()를 넣으면 해결된다.
에러 - 공백일 있을 경우 에러가 난다.
$ git add useful_code/한글 파일 깨짐 방지 코드.ipynb
fatal: pathspec 'useful_code/한글' did not match any files
해결법 - 역슬래시를 붙이면 제대로 된다.
$ git add useful_code/한글\ 파일\ 깨짐\ 방지\ 코드.ipynb
수정되거나 삭제된 파일 반영
git add -u
또한 git commit 에서 -a옵션을 붙여주게 되면 수정되거나 삭제된 파일만 commit하게 해준다.
git commit -a -m'message'
=> push까지 하면 github에 제대로 반영이 된다.
commit
- commit을 통해서 하나의 버전으로 기록됨
- commit 메시지는 현재의 변경 사항을 잘 나타내도록 ‘잘’ 써야함
- commit 내역은
$ git log라는 명령어로 확인할 수 있음
commit 메시지의 기본 구조
# -m(message)
$ git commit -m "남기고 싶은 메시지"
$ git commit -m "Initial commit"
[master (root-commit) acf00f0] Initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a.txt
commit 내역 확인
#
$ git log
commit acf00f0792da06e949f21997a4f4226dc64a3ea7 (HEAD -> master)
Author: ingu627 <rjsdudans@naver.com>
Date: Sun Nov 21 14:36:03 2021 +0900
Initial commit
commit 이력을 더 짧게 보기
$ git log --oneline
acf00f0 (HEAD -> master) Initial commit
git 로그 정지 탈출 방법
: Q를 누른다.
퀴즈! 만약 status를 여기서 찍으면 어떤 결과가 나올까?
- 현재
b.txt가 WD에 위치해있기 때문에 빨간색으로 표시된다. a.txt는 commit 명령어를 통해 하나의 버전으로 기록됨
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
b.txt
nothing added to commit but untracked files present (use "git add" to track)

2. 원격 저장소와 협업
기본 설정
- 내 로컬 컴퓨터의 폴더를 git이 관리하도록 설정한다.
# git으로 초기화
$ git init
Initialized empty Git repository in F:/TIL/.git/
# add & commit
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
a.txt
b.txt
nothing added to commit but untracked files present (use "git add" to track)
$ git add .
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: a.txt
new file: b.txt
$ git commit -m "Initial commit"
[master (root-commit) d2c6be1] Initial commit
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a.txt
create mode 100644 b.txt
- Github Repository 생성

public은 다 볼 수 있는 저장소이다.private은 나 또는 이 권한이 있는 유저만 볼 수 있는 저장소이다.
원격 저장소 등록 & 업로드 명령어
원격 저장소 추가
- 최초 1회만 설정하면 됨
# 원격 저장소 추가
# git아 원격 저장소 좀 등록해줘(add) origin이라는 이름(별명)으로 원격 저장소URL을
$ git remote add origin 원격저장소URL
- 원격저장소 url은 복사 붙여넣기 한다.

# 예시
$ git remote add origin https://github.com/IT3AI1/TIL.git
등록된 원격 저장소 확인
$ git remote -v
origin https://github.com/IT3AI1/TIL.git (fetch)
origin https://github.com/IT3AI1/TIL.git (push)
원격 저장소가 잘못 등록되어 삭제해야 하는 경우
$ git remote rm origin
$ git remote -v
원격 저장소에 나의 소스 코드 업로드
-
add, commit 이후에 원격 저장소에 나의 로컬 버전 기록을 업로드 하고 싶으면 push 진행
-
2.23 버전의 로그인 이슈
- 아래 명령어를 입력하고 다시 push 작업 진행
$ git config --global credential.git.github.com.provider generic- 혹은 vscode에 git bash를 연결해서 push하면 문제 해결 가능
$ git push -u origin master # 첫 git push를 하면 아래와 같이 인증을 요구하는 화면이 나옴
Select an authentication method for 'https://github.com/':
1. Web browser (default)
2. Personal access token
option (enter for default): # 바로 enter를 눌러서 진행
# 조금 기다린 뒤에 github 사이트로 들어가서 새로고침하면 로컬 저장소에 있는 모든 내역이 업로드 된 것을 확인할 수 있음
# 이후에는 add & commit을 진행하고 push를 하면 새로운 버전을 원격 저장소(github)에 업로드 할 수 있다.
$ git push -u origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 214 bytes | 214.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/IT3AI1/TIL.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

기본 루틴
$ git add .
$ git commit -m "커밋 메시지"
$ git push origin master # git아 버전 이력을 push 해줘 어디로?! origin(우리가 붙인 별명)으로 master 브랜치를!

Git에서 push는 로컬 저장소에서 관리한 버전 이력을 원격 저장소로 업로드하는 명령어이고, pull은 원격 저장소의 변경 사항을 받아오며, clone은 원격 저장소 전체를 복제한다. 이 글은 push·pull·clone의 사용법과 .gitignore, 그리고 push 에러 해결 방법을 정리한다.
push
-
로컬 저장소에서 관리한 버전 이력을 원격 저장소(github)으로 업로드 하는 명령어
$ git push origin master -
참고
$ git push -u origin master # 여기서 -u는 최초 1회만 붙이면 됩니다. (최소 1회 push 할 때만 붙이자!)
pull
- 원격 저장소의 변경 사항을 받아옴(업데이트)
- commit 내역을 기반으로 변경 사항을 새로 갱신하는 행위
$ git pull origin master # git아 pull(업데이트 해줘) origin 이라는 원격 저장소로부터 master 브랜치를!
$ git pull origin master
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 739 bytes | 67.00 KiB/s, done.
From https://github.com/IT3AI1/TIL
* branch master -> FETCH_HEAD
d2c6be1..29e2c44 master -> origin/master
Updating d2c6be1..29e2c44
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 README.md
- 원격저장소에
read.me를 추가한 후 pull을 한 결과이다.
clone
- 원격 저장소 전체를 복제
-
최초 1회만 수행
- 클론 받은 프로젝트는 자동으로
.git이 설정되어 있음 (+remote도 등록되어 있음)- 복제한거니까!
$ git clone 복제할저장소URL

만약 원격 저장소의 이름이 아닌 다른 이름으로 폴더를 clone 받고 싶다면?
$ git clone 원격저장소URL clone받을폴더이름
# 예시
$ git remote add origin https://github.com/IT3AI1/TIL.git TIL-test
push & pull(+clone) 시나리오
최초 1회 clone 이후 add, commit, push & pull, add, commit, push

gitignore
git이 어떠한 폴더 / 파일의 버전 관리를 무시할 수 있도록 적어두는 문서 -> 여기에 적힌 내용은 git이 버전 관리를 하지 않습니다.
- 일반적으로 개인정보 및 특정 사람에게만 적용되는 개발 환경과 같은 설정이 포함됨
- 개발할 때 사용하는 secret key, (보안상의 이유로) github과 같은 원격저장소에 업로드되면 안되는 정보 등은 git이 버전 관리를 하면 안됨
- 그리고 버전 관리가 필요없다고 생각되는 폴더 혹은 파일도 포함 시킬 수 있음
.gitignore파일을 만들어서 관리한다.- 일반적으로
git init을 진행하기 전에 만든다.
practice # 특정한 폴더를 git이 관리하지 않게함
a.txt # 특정한 파일을 git이 관리하지 않게함
*.txt # 특정한 확장자를 가진 파일을 git이 관리하지 않게함

gitignore.io
https://gitignore.io/
-
.vscode/.DS_Store-> 보안상의 이유가 아니더라도 버전 관리의 필요성이 없는 친구들이 존재..! - 미리 특정한 언어, 프레임워크, 운영 체제 등에서 git으로 버전 관리를 할 필요가 없는 요소를 누군가! 미리 만들어 놓았음
- 언어, 프레임워크, 운영체제 등을 검색하고 ‘생성’ 버튼을 누르면 자동으로 필요한 내용을 만들어 준다.
다시 정리!
- gitignore는 어느 시점에 만드는 것이 좋을까요?
- git init 전/후
- gitignore 파일이 위치하는 곳은 어디일까요?
- 일반적으로
.git폴더가 존재하는 곳에 생성
- 일반적으로
push error
$ git push origin main
To https://github.com/IT3AI1/practice.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/IT3AI1/practice.git' # 거절됨...
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
해석
# 원격 저장소로 push하는 것을 실패했음..
error: failed to push some refs to 'https://github.com/IT3AI1/practice.git'
# update가 reject되었는데 왜냐면... remote에 local 없는 어떤 변경 사항이 있음...
hint: Updates were rejected because the remote contains work that you do
# 이러한 상황은 커밋이 다른 경우에 발생하는데.. remote 저장소와 local 저장소를 일치 시켜야 할 것 같음...
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
# 어.. git pull 한번 해볼래?? 언제?? 다시 push 하기 전에...
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
- 로컬 저장소(내 컴퓨터)와 원격 저장소(github)의 commit 이력을 비교해본다!
- 이 문제는 로컬 저장소와 원격 저장소의 commit 이력이 다르기 때문에 발생하는 문제
- 주로 집에서 push를 하고 강의장에 가서 pull하지 않은 채로 작업하고 add, commit 이후에 push를 하면 보게 되는 메시지
- 로컬 저장소에서
$ git pull origin master를 진행한다. - vs code 창이 나오면 text 파일을 x 버튼을 눌러서 종료 한다.
- 이때 vs code 창이 열리지 않는 경우도 있기 때문에 당황하지 말 것!
3. 브랜치 전략과 병합(Merge)
참고: 이 포스트의 실습 예제는
master브랜치를 사용합니다. 새로운 프로젝트에서는main브랜치 사용을 권장합니다.
branch command
$ git init
Initialized empty Git repository in F:/branch_practice/.git/
$ touch a.txt
$ git add .
$ git commit -m 'Finish a.txt'
[master (root-commit) 31d9b7b] Finish a.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a.txt
브랜치 생성
$ git branch 브랜치이름
# 예시
$ git branch feature
브랜치 목록 확인
*가 찍혀있는 것은 현재 위치한 브랜치를 의미함
$ git branch
feature
* master
브랜치 이동
$ git checkout 브랜치이름
# 예시
$ git checkout feature
Switched to branch 'feature'
$ git branch
* feature
master
브랜치 생성 + 이동
$ git checkout -b 브랜치명
# 예시
$ git checkout -b feature2
Switched to a new branch 'feature2'
$ git branch
feature
* feature2
master
브랜치 병합 (merge)
HEAD: 현재 브랜치의 최신 커밋
# feature2 브랜치에서 b.txt 파일 생성 후 add, commit
$ touch b.txt
$ git add .
$ git commit -m "Finish b.txt in feature2 branch"
[feature2 b4c6264] Finish b.txt in feature2 branch
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
- feature2에서 b.txt를 생성했다. 이를 다시 master로 가서 feature2와 merge를 할 것이다.
# master 브랜치로 이동
$ git checkout master
Switched to branch 'master'
# merge
$ git merge 머지할브랜치이름
# 예시
$ git merge feature2
Updating 31d9b7b..b4c6264
Fast-forward
b.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
# 확인
$ git log
commit b4c6264a5c45aacb80d58851e6800848723c1122 (HEAD -> master, feature2)
Author: ingu627 <rjsdudans@naver.com>
Date: Sun Nov 21 16:11:05 2021 +0900
Finish b.txt in feature2 branch
commit 31d9b7b69c3441f83c1f05295c74ac519c797d87 (feature)
Author: ingu627 <rjsdudans@naver.com>
Date: Sun Nov 21 16:06:23 2021 +0900
Finish a.txt
브랜치 삭제
$ git branch -d 브랜치이름
# 예시
$ git branch -d feature2
Deleted branch feature2 (was b4c6264).
# 확인
$ git branch
feature
* master
branch 명령어
1. branch 생성
git branch 브랜치명
2. branch 이동
git checkout 브랜치명
3. branch 생성 & 이동
git checkout -b 브랜치명
4. branch 상태 확인 (local)
git branch
5. branch 상태 확인 (remote)
git branch -r
6. branch 상태 확인 (local + remote)
git branch -a
7. remote branch 가져오기
git checkout -t 닉네임/브랜치명
git checkout --track 닉네임/브랜치명
8. branch 병합
- 다른 브랜치를 현재 Checkout된 브랜치에 Merge 하는 명령
git merge 브랜치명
9. branch 삭제 (local)
git branch -d 브랜치명
10. branch 강제 삭제 (local)
git branch -D 브랜치명
11. branch 원격 저장소 삭제 (remote)
git push origin -d 브랜치명
git push origin --delete 브랜치명
12. 유효하지 않은 branch 업데이트 (청소) (remote내에서)
- 리모트 브랜치의 더 이상 유효하지 않은 참조를 깨끗이 지우는 명령어
git remote prune origin
git remote update --prune
13. branch 로컬 업데이트
- 로컬 저장소를 최신 정보로 갱신(리모트 저장소와 동기화)하며 자동적으로 더이상 유효하지 않은 참조를 제거한다.
git fetch -p
14. commit 기록 그래프화
git log --all --oneline --graph
15. branch 업로드
git push origin 브랜치명
16. branch명 변경
git branch -m 브랜치명 새로운 브랜치명
17. merge여부 branch 보여줌
- 현재 Checkout한 브랜치에 Merge한 브랜치를 살펴본다.
- 현재 Checkout한 브랜치에 Merge하지 않은 브랜치를 살펴본다.
git branch --merged
git branch --no-merged
branch scenario
1. branch 사용법
중요: 브랜치를 조작할 때는 반드시
master브랜치에 최소 1개의 커밋이 있어야 합니다!
실습 준비
- 따라해 본다.
# git 초기화 및 commit 남겨놓기
$ git init
$ touch a.txt
# a.txt에 text 1이라는 글을 작성한다.
$ git add .
$ git commit -m'text2'
[master 67f01f6] text2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
# 3개의 커밋을 더 남긴다.
$ git log --oneline
b9aaaf5 (HEAD -> master) test3
67f01f6 text2
acf00f0 Initial commit
HEAD
-
https://stackoverflow.com/questions/2304087/what-is-head-in-git
- 현재 위치한 브랜치의 최신 커밋
- HEAD는 현재 브랜치를 가리키는 포인터
ex. 이제 우리는 로그인 기능을 개발해본다고 가정
$ git branch feature/login # 브랜치 생성만
$ git branch
feature/login
* master
master 브랜치에서 마지막 줄 추가
text 1
text 2
text 3
master에서 작성한 text 4 # 추가
# add, commit
$ touch d.txt # master에서 d.txt를 생성했다.
$ git add .
$ git commit -m'master text 4'
[master 121a503] master text 4
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d.txt
# log
$ git log --oneline
121a503 (HEAD -> master) master text 4
b9aaaf5 (feature/login) test3
67f01f6 text2
acf00f0 Initial commit
브랜치 이동을 하고 a.txt를 확인해보자
$ git checkout feature/login
Switched to branch 'feature/login'
# master text 4가 사라짐
# log 확인
$ git log --oneline
b9aaaf5 (HEAD -> feature/login) test3
67f01f6 text2
acf00f0 Initial commit
# 현재 브랜치는 feature/login
text 1
text 2
text 3
login text 4 # 추가
브랜치를 다룰 때는 현재 내가 ‘어떤’ 브랜치에 있는지를 반드시 알아야 합니다!
# login.txt
login text 4 # 추가
$ touch login.txt
$ git status
On branch feature/login
Untracked files:
(use "git add <file>..." to include in what will be committed)
login.txt # WD + commit 이력 없음(git이 지금까지 한번도 추적한적 없음)
nothing added to commit but untracked files present (use "git add" to track)
# add, commit
$ git add .
$ git commit -m'login text4'
[feature/login f6dda89] login text4
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 login.txt
# 현재 브랜치는? feature/login
$ git log --oneline
f6dda89 (HEAD -> feature/login) login text4
b9aaaf5 test3
67f01f6 text2
acf00f0 Initial commit
# 다른 브랜치의 그래프까지 보는 방법
$ git log --all --graph --oneline
* f6dda89 (HEAD -> feature/login) login text4
| * 121a503 (master) master text 4
|/
* b9aaaf5 test3
* 67f01f6 text2
* acf00f0 Initial commit
2. branch merge scenario
-
드라이브에 git-merge 폴더 생성 후 해당 폴더에서 VS Code를 열자!

-
Ctrl + 백틱(1왼쪽에 있는)을 누른 후Git Bash클릭 후 작업

$ git init
Initialized empty Git repository in F:/git-merge/.git/
$ touch test.txt
- test.txt에 master test 1이라고 채워넣기 (저장 꼭!!)

$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.txt
nothing added to commit but untracked files present (use "git add" to track)
$ git add .
$ git commit -m'master test 1'
[master (root-commit) 9fe5f83] master test 1
1 file changed, 1 insertion(+)
create mode 100644 test.txt
# log
$ git log
commit 9fe5f839afe5de4e366dc981f62f9692cce859ee (HEAD -> master)
Author: ingu627 <rjsdudans@naver.com>
Date: Sun Nov 21 19:41:06 2021 +0900
master test 1
3가지 병합 상황
1. fast-forward

주의사항: 반드시 master 브랜치에는 1개 이상의 커밋이 존재해야 합니다!
“다른 브랜치가 생성된 이후에 master 브랜치의 변경 사항이 없는 상황 => 단순하게 master 브랜치의 포인터를 최신 commit으로 이동시킨다.”
master 브랜치에서 feature/login 브랜치를 병합(merge) 할 때 feature/login 브랜치가 master 브랜치 이후의 commit을 가리키고 있다면 master 브랜치는 feature/login 브랜치가 가리키고 있는 최신 commit으로 포인터(HEAD)를 이동시키면 된다.
1. feature/login 브랜치 생성 후 이동
$ git checkout -b feature/login
Switched to a new branch 'feature/login'
2. 특정한 작업을 완료하고 commit 진행
$ touch login.txt
$ git add .
$ git commit -m'login test 1'
[feature/login 6302c25] login test 1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 login.txt
# log
$ git log --oneline
# master 브랜치에서 feature/login 브랜치 생성 -> feature/login 브랜치에서 새로운 commit 생성
6302c25 (HEAD -> feature/login) login test 1
9fe5f83 (master) master test 1

3. master 브랜치로 이동
- 브랜치를 이동하는 순간 login.txt 파일이 사라진다.
- 왜냐하면 login.txt 파일은 master 브랜치가 아니라 feature/login 브랜치에서 commit(버전)을 했기 때문임
$ git checkout master
Switched to branch 'master'

4. master 브랜치에 feature/login 브랜치에서 작업한 결과물 병합
- 병합 이후에 login.txt 파일이 생김
병합 규칙: 병합하고자 하는 브랜치로 이동한 후 작업합니다.
$ git merge feature/login
Updating 9fe5f83..6302c25
Fast-forward
login.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 login.txt

5. 로그 확인
- HEAD -> master가 위로 올라왔음!
# 병합 전
$ git log --oneline
# master 브랜치에서 feature/login 브랜치 생성 -> feature/login 브랜치에서 새로운 commit 생성
6302c25 (HEAD -> feature/login) login test 1
9fe5f83 (master) master test 1
# 병합 후
$ git log --oneline
6302c25 (HEAD -> master, feature/login) login test 1
9fe5f83 master test 1
6. 브랜치 삭제
$ git branch -d feature/login
Deleted branch feature/login (was 6302c25).
# 확인
$ git branch
* master
$ git log --oneline
6302c25 (HEAD -> master) login test 1
9fe5f83 master test 1
2. Merge commit -> conflict x

다른 브랜치(feature/signup)가 생성된 이후에 master 브랜치에 변경 사항이 있고 feature/signup 브랜치에도 변경 사항이 존재하는 경우 -> 이때 충돌 상황이 발생하지 않는 경우
-
다른 파일의 변경 사항을 작성(수정) commit한 경우
Merge commit이 발생함- 이 commit 내역은 우리가 직접 작성한 commit이 아닌 git이 자동으로 작성해준 commit message
- 충돌이 발생하지 않는 이유는 다른 파일 (같은 파일이라도 다른 라인을 수정한 경우 포함)이기 때문에 단순하게 합치기만 하면 되기 때문!
1. signup 브랜치 생성 & 이동
git checkout -b 브랜치이름: 이름명으로 생성하고 그 브랜치로 이동
$ git checkout -b feature/signup
Switched to a new branch 'feature/signup'
2. 특정한 작업을 진행하고 commit
$ touch signup.txt
# add, commit
$ git add .
$ git commit -m'signup test 1'
[feature/signup 586d298] signup test 1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 signup.txt
# log
$ git log --oneline
586d298 (HEAD -> feature/signup) signup test 1 # feature/signup 브랜치의 최신 커밋 + 현재 내가 위치한 브랜치
6302c25 (master) login test 1 # master 브랜치의 최신 커밋
9fe5f83 master test 1

3. master로 이동
- 이동하는 순간 signup.txt 파일이 사라짐
- signup 브랜치에서 파일을 생성하고 commit 했기 때문!
$ git checkout master
Switched to branch 'master'
$ git log --oneline
6302c25 (HEAD -> master) login test 1
9fe5f83 master test 1

4. master 브랜치에서 추가 작업을 진행한 다음 commit
$ touch master.txt
# add, commit
$ git add .
$ git commit -m'master test 1'
[master 2c9f3c0] master test 1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master.txt
# log
$ git log --oneline
2c9f3c0 (HEAD -> master) master test 1
6302c25 login test 1
9fe5f83 master test 1
# 브랜치 포함 모든 log를 확인할 때
$ git log --all --oneline
2c9f3c0 (HEAD -> master) master test 1
586d298 (feature/signup) signup test 1
6302c25 login test 1
9fe5f83 master test 1
5. master 브랜치에 병합
- merge를 진행하고나서 확인해보니 signup.txt가 생기는 걸 확인할 수 있음
$ git merge feature/signup
Merge made by the 'recursive' strategy.
signup.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 signup.txt
# log
$ git log --oneline
6e469f3 (HEAD -> master) Merge branch 'feature/signup' # 우리가 직접 입력한 commit x -> Merge commit
2c9f3c0 master test 1
586d298 (feature/signup) signup test 1
6302c25 login test 1
9fe5f83 master test 1
6. log
- graph로 보고자 할 때
$ git log --all --graph --oneline
* 6e469f3 (HEAD -> master) Merge branch 'feature/signup'
|\
| * 586d298 (feature/signup) signup test 1
* | 2c9f3c0 master test 1
|/
* 6302c25 login test 1
* 9fe5f83 master test 1
7. branch 삭제
$ git branch -d feature/signup
Deleted branch feature/signup (was 586d298).
$ git log --all --graph --oneline
* 6e469f3 (HEAD -> master) Merge branch 'feature/signup'
|\
| * 586d298 signup test 1
* | 2c9f3c0 master test 1
|/
* 6302c25 login test 1
* 9fe5f83 master test 1
3. Merge commit -> conflict o
다른 브랜치(feature/signup)가 생성된 이후에 master 브랜치에 변경 사항이 있고 feature/signup 브랜치에도 변경 사항이 존재하는 경우 -> 이때 충돌 상황이 발생하는 경우
-
같은 파일의 같은 부분을 작성(수정)하여 commit한 경우
Merge commit이 발생함- 이 commit 내역은 우리가 직접 작성한 commit이 아닌 git이 자동으로 작성해준 commit message
- 충돌이 발생하는 이유는 같은 파일의 같은 부분을 수정했기 때문에 어떤 버전으로 만들지 git은 알 수 없기 때문!
- 그래서 직접 우리가(==사람이) 수정해줘야 한다.
1. hotfix 브랜치 생성 후 이동
$ git checkout -b hotfix
Switched to a new branch 'hotfix'
2. 특정 작업 완료 후 & commit 진행
# hotfix branch의 test.txt
master test 1
이건 hotfix 브랜치에서 # 추가
수정했습니다.

$ git add .
$ git commit -m'hotfix test 1'
[hotfix 03ba33b] hotfix test 1
1 file changed, 3 insertions(+), 1 deletion(-)
$ git log --oneline
03ba33b (HEAD -> hotfix) hotfix test 1
6e469f3 (master) Merge branch 'feature/signup'
2c9f3c0 master test 1
586d298 signup test 1
6302c25 login test 1
9fe5f83 master test 1
3. master로 이동
$ git checkout master
Switched to branch 'master'
4. 특정 작업 후 commit
- hotfix 브랜치에서 작업한 부분과 동일한 부분을 수정
# master branch의 test.txt
master test 1
이건 master 브랜치에서 # 추가
수정한 내용입니다.

$ git add .
$ git commit -m'master test 1'
[master b74a431] master test 1
1 file changed, 3 insertions(+), 1 deletion(-)
# log
$ git log --oneline
b74a431 (HEAD -> master) master test 1
6e469f3 Merge branch 'feature/signup'
2c9f3c0 master test 1
586d298 signup test 1
6302c25 login test 1
9fe5f83 master test 1
5. Merge
$ git merge hotfix
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt # 충돌.. -> merge 하는 과정에서 충돌이 발생함 -> test.txt
# 자동으로 병합하는 것 실패! -> 충돌을 해결하고 난 다음에 그 결과를 commit 하세요
Automatic merge failed; fix conflicts and then commit the result.

-
같은 부분(라인)을 다른 브랜치에서 각각 수정하고 commit 했기 때문에 병합하는 과정에서 git은 어떤 부분을 합쳐야 하는지 알 수 없음 -> 그래서 우리가 직접 합치고 나서 merge commit을 발생시켜야 한다.
master test 1 <<<<<<< HEAD 이건 master 브랜치에서 수정한 내용입니다. ======= 이건 hotfix 브랜치에서 수정했습니다. >>>>>>> hotfix

# 수정
master test 1
이건 master 브랜치에서
수정한 내용입니다.
이건 hotfix 브랜치에서
수정했습니다.
# master | MERGING -> Merge commit을 남겨야 함

$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: test.txt # both modified
no changes added to commit (use "git add" and/or "git commit -a")
# add로 올리고 commit으로 Merge commit을 직접 남긴다.
$ git add .
$ git commit -m "충돌 해결!"
[master 03c4743] 충돌 해결!
6. log 확인
- 충돌이 발생하지 않은 경우에는
6e469f3 (HEAD -> master) Merge branch 'feature/signup'이러한 commit을 git이 자동으로 만들어주지만 충돌을 직접 해결하는 경우 우리가 충돌을 해결했다는 의미의 커밋을 직접 남길 수 있다.
$ git log --oneline
03c4743 (HEAD -> master) 충돌 해결!
b74a431 master test 1
03ba33b (hotfix) hotfix test 1
6e469f3 Merge branch 'feature/signup'
2c9f3c0 master test 1
586d298 signup test 1
6302c25 login test 1
9fe5f83 master test 1
7. branch 삭제
$ git branch -d hotfix
Deleted branch hotfix (was 03ba33b).
# log
$ git log --all --oneline --graph
* 03c4743 (HEAD -> master) 충돌 해결!
|\
| * 03ba33b hotfix test 1
* | b74a431 master test 1
|/
* 6e469f3 Merge branch 'feature/signup'
|\
| * 586d298 signup test 1
* | 2c9f3c0 master test 1
|/
* 6302c25 login test 1
* 9fe5f83 master test 1
4. 변경 사항 되돌리기(Undoing)
undoing은 어떤 행위를 취소할 때 사용하는 명령어다. 이 글은 파일을 Unstage로 되돌리는 git rm --cached와 git restore --staged, Modified 파일을 되돌리는 git restore, 완료된 커밋을 수정하는 git commit --amend, 그리고 reset과 revert의 차이를 정리한다.
undoing
-
어떤 행위를 취소할 때 사용하는 명령어
-
사전 준비
# git 초기화 & a.txt README.md 파일 생성

1. 파일 상태를 Unstage로 변경하기
Staging Area(INDEX)와 Working Directory(WA)를 넘나드는 방법
첫 번째 - rm --cached
- 따로 따로 커밋하려고 했지만 실수로 모두
$ git add .를 한 상황 (처음으로 add를 하는 상황이라고 가정)
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
a.txt
nothing added to commit but untracked files present (use "git add" to track)
$ git add .
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage) # rm --cached를 써 ... 무대에서 내리고 싶으면..!
new file: README.md
new file: a.txt
a.txt를 add하기 전으로 돌린다.
$ git rm --cached a.txt
rm 'a.txt'
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
a.txt # 무대에서 내려옴!!

commit 남겨보자!
$ git add .
$ git commit -m'first commit'
[master (root-commit) a46391e] first commit
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
create mode 100644 a.txt
두 번째 - restore
-
두 개의 파일을 모두 수정하고 따로따로 커밋하려고 했지만, 실수로
$ git add .라고 해버린 상황 -
a.txt, README.md 파일에 각각 메시지를 남겨보자

$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory) # WD에 있음 + commit이 한번이라고 발생 했던 친구? 넵! -> modified!
modified: README.md
modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git add .
# status
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
modified: a.txt
$ git restore --staged a.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt

첫 번째와 두 번째 뭐가 다를까?
bash로 볼 때
$ touch b.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md # SA + commit이 한번이라도있었던 -> restore --staged
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in
working directory)
modified: a.txt # WD + commit이 한번이라도 있었던
Untracked files:
(use "git add <file>..." to include in what will be committed)
b.txt # WD + commit이 한번도 안된 친구
다시 정리하면
git rm --cached <file>- 기존에 커밋이 없는 경우 SA -> WD로 내릴 때 사용
git restore --staged <file>- 기존에 커밋이 있는 경우 SA -> WD로 내릴 때 사용
2. Modified된 파일 되돌리는 방법
- add가 되어있지 않은(WD에 있는) + 수정된(modified) a.txt를 다시 돌려보자
- 일단 commit은 적어도 한번 있었고 수정되었음
- 하지만 SA에 올라가지 않은 상태
주의!!!!
- 원래 파일로 돌아갔기 때문에 ‘절대로’ 다시 되돌릴 수 없음
- 수정한 내용이 마음에 들지 않을 때만 사용해야 함(정말 마음에 안들때만 써야함)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in
working directory)
modified: a.txt # 이녀석을 수정 전 상태로 돌릴 예정
Untracked files:
(use "git add <file>..." to include in what will be committed)
b.txt
# 기존에 a.txt에 작성된 내용이 모두 사라짐
$ git restore a.txt
# status -> 애초에 commit으로 남기지 않았기 때문에 돌릴 수 없음
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
b.txt
3. 완료된 커밋 수정
$ git commit --amend
- 커밋 메시지를 잘못 적은 경우 수정!!
- 가장 최신의 commit만 수정 가능함..!
- 역사를 바꾸려고 하면 안됨..!
- 너무 일찍 커밋을 한 경우(무언가 빼먹고 commit을 진행한 경우)
[주의 사항] :커밋 메시지를 바꾸면 커밋 해시값이 변하기 때문에 원격 저장소에 업로드한 경우 커밋 메시지는 절대로 수정하지 말 것! amend 는 로컬에서만 사용한다.
3.1 커밋 메시지 수정
- 수정을 진행하고 창을 닫아주면 됩니다.
$ git add .
$ git commit -m'amend text file' # 오타가 났다.
[master 2cc67ed] amend text file
2 files changed, 3 insertions(+)
create mode 100644 b.txt
# 수정 진행
# amend text file -> 이 부분 수정
$ git commit --amend -m 'text file'
[master d984105] text file
Date: Sun Nov 21 22:11:31 2021 +0900
2 files changed, 3 insertions(+)
create mode 100644 b.txt

3-2. 어떠한 파일을 빼먹고 commit을 한 경우
다시 커밋을 하고 싶으면 수정 작업을 하고 SA에 추가한 다음
--amend옵션을 사용하여 커밋 재작성
$ touch foo.txt bar.txt
$ git add foo.txt
# 상태 확인
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: foo.txt # SA + new file -> commit이 한번도 없었던 상태
Untracked files:
(use "git add <file>..." to include in what will be committed)
bar.txt # WD
# 실수로 bar.txt를 빼먹고 커밋을 진행함
$ git commit -m'foo & bar'
[master 48f0541] foo & bar
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 foo.txt
# log
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
bar.txt # bar는 WD에 남아있음!
nothing added to commit but untracked files present (use "git add" to track)
해결하기
$ git add bar.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: bar.txt
$ git add bar.txt
$ git commit --amend -m'foo & bar'
[master d6175dd] foo & bar
Date: Sun Nov 21 22:22:41 2021 +0900
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar.txt
create mode 100644 foo.txt
# 상태 확인
$ git status
On branch master
nothing to commit, working tree clean
# log 확인
$ git log --oneline
d6175dd (HEAD -> master) foo & bar # 새로운 커밋이 생긴게 아니라 기존 커밋에 bar.txt의 변경 사항만 추가됨
d984105 text file
a46391e first commit
reset vs revert
reset
- https://git-scm.com/docs/git-reset
- “시계를 마치 과거로 돌리는 듯한 행위”
- 특정 커밋으로 되돌아가며 되돌아간 특정 커밋 이후의 커밋들은 모두 사라지며, 파일 상태는 옵션을 통해 결정
3가지 옵션
1. --soft
- reset하기 전까지 했던 SA, WD 작업은 남겨둠
- 돌아가려는 커밋으로 되돌아가고,
- 이후의 commit된 파일들을
staging area로 돌려놓음 (commit 하기 전 상태) - 즉, 바로 다시 커밋할 수 있는 상태가 됨
2. --mixed
- (기본) SA reset, WD작업은 남겨둠
- 돌아가려는 커밋으로 되돌아가고,
- 이후의 commit된 파일들을
working directory로 돌려놓음 (add 하기 전 상태) - 즉, unstaged 된 상태로 남아있음
- 기본값
3. --hard
- reset하기 전 SA, WD 모든 작업 리셋
- 돌아가려는 커밋으로 되돌아가고,
- 이후의 commit된 파일들(
tracked 파일들)은 모두 working directory에서 삭제 - 단, Untracked 파일은 Untracked로 남음

# undoing 폴더에서 했던 내용 이어서 진행
# --hard 예시
$ git log --oneline
d6175dd (HEAD -> master) foo & bar
d984105 text file
a46391e first commit
$ git reset --hard d984105
HEAD is now at d984105 text file
$ git log --oneline
d984105 (HEAD -> master) text file
a46391e first commit
$ git status
On branch master
nothing to commit, working tree clean
reset 특징들
reset은 과거로 돌아가게 되면 돌아간 커밋 이후의 커밋은 모두 히스토리에서 사라짐- 커밋 히스토리가 바뀌기 때문에 다른 사람과 공유하는 브랜치에서 사용 시 충돌이 발생
- 공유하는 브랜치에서 이전 커밋을 수정하고 싶을 때는
git revert사용
revert
-
https://git-scm.com/docs/git-revert
- “특정 사건을 없었던 일로 만드는 행위”
- 이전 커밋 내역을 그대로 남겨둔 채 새로운 커밋(==없었던 일입니다!를 의미하는 commit)을 생성
- 커밋 히스토리 변경 없이 해당 커밋 내용만을 삭제한 상태의 새로운 커밋을 생성

추가 commit 2개만 더 남기자
# undoing에서 이어서 진행
$ touch c.txt d.txt
$ git add c.txt
$ git commit -m "Add c.txt"
[master d9c38f7] Add c.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c.txt
$ git add d.txt
$ git commit -m "Add d.txt"
[master aaf2db9] Add d.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d.txt
$ git log --oneline
aaf2db9 (HEAD -> master) Add d.txt
d9c38f7 Add c.txt
d984105 text file
a46391e first commit
revert commit 편집기 실행
- 다른 사람과 공유하는 브랜치에서 이전 커밋을 수정하고 싶을 때 사용
- 커밋 히스토리가 바뀌지 않기 때문에 충돌이 발생하지 않음
$ git revert d984105
Removing b.txt
hint: Waiting for your editor to close the file... error: There was a problem
with the editor 'vi'.
Please supply the message using either -m or -F option.
$ git log --oneline
# 기존 commit 이력이 그대로 남아있기 때문에 해당 하는 시점으로 언제든
aaf2db9 (HEAD -> master) Add d.txt
d9c38f7 Add c.txt
d984105 text file
a46391e first commit
정리


그외 방법
$ git reflog
aaf2db9 (HEAD -> master) HEAD@{0}: reset: moving to aaf2db9
d47f656 HEAD@{1}: reset: moving to d47f656
d47f656 HEAD@{2}: commit: text file amend
aaf2db9 (HEAD -> master) HEAD@{3}: commit: Add d.txt
d9c38f7 HEAD@{4}: commit: Add c.txt
d984105 HEAD@{5}: reset: moving to d984105
d6175dd HEAD@{6}: commit (amend): foo & bar
48f0541 HEAD@{7}: commit: foo & bar
d984105 HEAD@{8}: commit (amend): text file
2cc67ed HEAD@{9}: commit: amend text file
a46391e HEAD@{10}: commit (initial): first commit
-
reflog는 이런식으로 이전까지했던 작업들 reflog를 확인해 몇번째 HEAD로 이동할지 확인한다. -
만약 HEAD@{7}로 이동할꺼라면
$ git reset --hard HEAD@{7}
5. 핵심 요약 치트시트 & References
5.1 Git 핵심 명령어 치트시트
| 분류 | 명령어 | 설명 |
|---|---|---|
| 설정 | git config --global user.name "이름" |
커밋 작성자 이름 설정 |
git config --global user.email "이메일" |
커밋 작성자 이메일 설정 | |
git config --global core.editor "code --wait" |
기본 커밋 에디터를 VS Code로 변경 | |
| 기초 | git init |
현재 디렉토리를 로컬 Git 저장소로 초기화 |
git status |
워킹 디렉토리와 스테이징 영역의 파일 상태 확인 | |
git add <파일명> (git add .) |
변경된 파일을 Staging Area에 추가 | |
git commit -m "메시지" |
스테이지된 변경 사항을 버전으로 기록 | |
git log --oneline --graph --all |
커밋 히스토리를 한눈에 그래프로 확인 | |
| 원격 | git remote add origin <URL> |
원격 저장소 등록 |
git push -u origin <브랜치명> |
로컬 커밋 이력을 원격 저장소로 업로드 (최초 -u) | |
git pull origin <브랜치명> |
원격 저장소의 최신 커밋을 가져와 병합 | |
git clone <URL> |
원격 저장소를 로컬로 복제 (.git 자동 설정) | |
| 브랜치 | git branch <이름> |
새로운 브랜치 생성 |
git checkout <이름> / git switch <이름> |
지정 브랜치로 이동 | |
git checkout -b <이름> / git switch -c <이름> |
브랜치 생성과 동시에 이동 | |
git merge <브랜치명> |
현재 브랜치에 대상 브랜치 병합 | |
git branch -d <이름> |
병합 완료된 브랜치 삭제 (-D: 강제 삭제) | |
| 되돌리기 | git restore --staged <파일> |
Staging Area에서 워킹 디렉토리로 내리기 (Unstage) |
git restore <파일> |
워킹 디렉토리의 수정 사항 취소 (Modified 취소) | |
git commit --amend |
직전 커밋 메시지 수정 또는 파일 누락 반영 | |
git reset --soft <커밋ID> |
커밋 취소 + Staged 상태 유지 | |
git reset --mixed <커밋ID> |
기본값: 커밋 및 스테이지 취소 (WD 수정 유지) | |
git reset --hard <커밋ID> |
커밋, 스테이지, 워킹 디렉토리 변경 완전 폐기 | |
git revert <커밋ID> |
기존 커밋을 취소하는 새로운 반대 커밋 생성 | |
git reflog |
HEAD의 모든 이동 이력 조회 (유실된 커밋 복구) |
댓글남기기