아래 글은 'いまさらだけどGitを基本から分かりやすくまとめてみた'을 번역하여 정리한 글입니다.
출처: https://qiita.com/gold-kou/items/7f6a3b46e2781b0dd4a0
# [방법 1] commit을 취소하고 해당 파일들은 staged 상태로 워킹 디렉터리에 보존
$ git reset --soft HEAD^
# [방법 2] commit을 취소하고 해당 파일들은 unstaged 상태로 워킹 디렉터리에 보존
$ git reset --mixed HEAD^ # 기본 옵션
$ git reset HEAD^ # 위와 동일
$ git reset HEAD~2 # 마지막 2개의 commit을 취소
# [방법 3] commit을 취소하고 해당 파일들은 unstaged 상태로 워킹 디렉터리에서 삭제
$ git reset --hard HEAD^
# 출처: https://gmlwjd9405.github.io/2018/05/25/git-add-cancle.html
# a.txt를 취소
$ ls
README.md
# reflog 확인。HEAD@{0}로 reset한 이력이 남아 있음
$ git reflog
63678f0 HEAD@{0}: reset: moving to HEAD@{1}
08f9902 HEAD@{1}: commit: Add a.txt
63678f0 HEAD@{2}: clone: from http://XXXXX
# HEAD@{0} reset보다 전으로 돌아가는 것으로 reset을 취소
$ git reset --hard HEAD@{1}
HEAD is now at 08f9902 Add a.txt
# a.txt가 돌아간 것을 확인
$ ls
README.md a.txt
# reflog 확인. 새로운 reset 이력이 있음
$ git reflog
08f9902 HEAD@{0}: reset: moving to HEAD@{1} # 새 이력
63678f0 HEAD@{1}: reset: moving to HEAD@{1}
08f9902 HEAD@{2}: commit: Add a.txt
63678f0 HEAD@{3}: clone: from http://XXXXX
A--B ←master
\
C ←sample
A--B---C ←master
\ /
C ←sample
# 1. 새로운 브랜치 생성
$ git checkout -b sample
# 2. 현재 브랜치 조회
$ git branch
master
* sample
# 3. 현재 디렉토리 내 파일 조회
$ ls
README.md
# 4. sample 브랜치에 새로운 파일 생성 후 커밋
$ touch a.txt
$ git add a.txt
$ git commit -m "Add a.txt"
[sample5 7525ea8] Add a.txt
1 file changed, 1 insertion(+)
create mode 100644 a.txt
# 5. master 브랜치로 이동
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
# 6. sample 브랜치의 커밋을 master 브랜치에 머지
$ git merge sample
Updating cfec4a3..7525ea8
Fast-forward
a.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 a.txt
# 7. 현재 디렉토리 내 파일 재조회
$ ls
README.md a.txt
A--B--D ←master
\
C ←sample
A--B--D--E ←master
\ /
C ←sample
# 1. sample 브랜치 작성
$ git branch sample
# 2. 브랜치 조회
$ git branch
* master
sample
# 3. 현재 디렉토리의 파일 조회
$ ls
README.md
# 4. master 브랜치에서 a.text를 생성하고 커밋. sample 브랜치에서 보면 master 브랜치가 커밋이 한 단계 진행되어 있는 상태
$ touch a.txt
$ git add a.txt
$ git commit -m "Add a.txt"
[master 66ea8cb] Add a.txt
1 file changed, 1 insertion(+)
create mode 100644 a.txt
# 5. sample 브랜치로 이동
$ git checkout sample
# 6. sample 브랜치에서 b.txt를 생성하고 커밋
$ touch b.txt
$ git add b.txt
$ git commit -m "Add b.txt"
[sample 6c92a36] Add b.txt
1 file changed, 1 insertion(+)
create mode 100644 b.txt
# 7. master 브랜치로 이동
$ git checkout master
Switched to branch 'master'
# 8. sample 브랜치의 커밋을 부모 브랜치(master)에 머지. non-fast-forward를 위해 머지-커밋 실시
$ git merge sample
--------------------------------------------
머지-커밋을 하기 위해 아래와 같은 안내문이 표시
Merge branch 'sample'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
--------------------------------------------
Merge made by the 'recursive' strategy.
b.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 b.txt
# 9. 파일 조회
$ ls
README.md a.txt b.txt
# 1. 파생 브랜치 생성
$ git branch
* master
$ git branch sample1
$ git branch sample2
# 2. sample1 브랜치로 이동
$ git checkout sample1
Switched to branch 'sample1'
# 3. a.txt를 생성하고 add -> commit -> push 실시
$ touch a.txt # aaa 입력 후 저장
$ cat a.txt
aaa
$ git add a.txt
$ git commit -m "Add a.txt"
$ git push origin sample1
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 271 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Updating references: 100% (1/1)
To http://xxxxx
* [new branch] sample1 -> sample1
# push한 내용을 리모트 레포에서 머지, sample2 브랜치의 기준에선 늦어져 있는 상태가 됨
# 4. sample2 브랜치로 이동
$ git checkout sample2
Switched to branch 'sample2'
# 5. b.txt를 생성하고 add -> commit -> push 실시
$ touch b.txt
$ git add b.txt
$ git commit -m "Add b.txt"
[sample2 b08565c] Add b.txt
1 file changed, 1 insertion(+)
create mode 100644 b.txt
$ git push origin sample2
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 273 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Updating references: 100% (1/1)
To http://XXXXX
* [new branch] sample2 -> sample2
# 현재 origin 리모트 레포의 master 브랜치에 rebase 실시
$ git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: Add b.txt
# sample1 브랜치에서 생성한 a.txt가 들어있는 것을 확인
$ ls
README.md a.txt b.txt
# 재push, rebase한 후의 push는 f(force) 옵션이 필요
$ git push origin sample2 -f
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 304 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Updating references: 100% (1/1)
To http://xxxxx
+ b08565c...1910d84 sample2 -> sample2 (forced update)
# 1. 파생 브랜치를 생성
$ git branch
* master
$ git branch sample1
$ git branch sample2
# 2. sample1 브랜치로 이동
$ git checkout sample1
Switched to branch 'sample1'
# 3. a.txt를 수정하고 add -> commit -> push 실시
$ touch a.txt # aaa ccc 입력 후 저장
$ cat a.txt
aaa
ccc
$ git add a.txt
$ git commit -m "Modify a.txt ccc"
[sample1 417b2d8] Modify a.txt ccc
1 file changed, 1 insertion(+)
# 4. sample1을 remote repo에 push
$ git push origin sample1
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 584 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
remote: Updating references: 100% (1/1)
To http://XXXXX
* [new branch] sample1 -> sample1
# 브라우저(깃헙) 상의 리모트 레포에서 머지. sample2는 master와 비교해서 늦어진 상황
# 5. sample2로 이동
$ git checkout sample2
# 6. a.txt를 수정하고 add -> commit -> push 실시
$ touch a.txt # aaa ddd 입력 후 저장
$ cat a.txt
aaa
ddd
$ git add a.txt
$ git commit -m "Modify a.txt ddd"
[sample2 58af6b0] Modify a.txt ddd
1 file changed, 1 insertion(+)
$ git push origin sample2
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 311 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Updating references: 100% (1/1)
To http://XXXXX
* [new branch] sample2 -> sample2
# 1. rebase 실행하면 충돌때문에 실패
$ git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: Modify a.txt ddd
Using index info to reconstruct a base tree...
M a.txt
Falling back to patching base and 3-way merge...
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
error: Failed to merge in the changes.
Patch failed at 0001 Modify a.txt ddd
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
# 2. 브랜치를 확인. rebase중인 것을 확인
$ git branch
* (no branch, rebasing sample2)
master
sample1
sample2
# 3. 해당 파일의 충돌을 해결
$ open a.txt # 파일을 열고 충돌되는 부분 수정
# vscode나 vi 등으로 확인해 보면 아래와 같이 diff가 표시됨
-------------------------------------------------------
aaa
<<<<<<< 3639ad3cc4a0208ba8201ad074accdb31d9348d8
ccc
=======
ddd
>>>>>>> Modify a.txt ddd
-------------------------------------------------------
# 4. 충돌된 부분을 해결(sample1과 sample2의 변경사항을 둘 다 반영)
-------------------------------------------------------
aaa
ccc
ddd
-------------------------------------------------------
# 5. 수정한 파일 add
$ git add a.txt
# 6. rebase 완료
$ git rebase --continue
Applying: Modify a.txt ddd
# 7. 브랜치 확인. rebase 상태가 아닌 것을 확인
$ git branch
master
sample1
* sample2
# 8. 재push。rebase한 후에 push는 f(force) 옵션 필요
$ git push origin sample2 -f
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 318 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Updating references: 100% (1/1)
To http://XXXXX
+ 58af6b0...0731fcc sample2 -> sample2 (forced update)
$ git checkout master
$ git pull