Git 변경 되돌리기: 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}
댓글남기기