6 분 소요


undoing

  • 어떤 행위를 취소할 때 사용하는 명령어

  • 사전 준비

# git 초기화 & a.txt README.md 파일 생성

image



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 # 무대에서 내려옴!!

image-20210706143516204



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 파일에 각각 메시지를 남겨보자

image

$ 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

image-20210706143940012



첫 번째와 두 번째 뭐가 다를까?

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이 한번도 안된 친구



다시 정리하면

  1. git rm --cached <file>
    • 기존에 커밋이 없는 경우 SA -> WD로 내릴 때 사용
  2. 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
  1. 커밋 메시지를 잘못 적은 경우 수정!!
    • 가장 최신의 commit만 수정 가능함..!
    • 역사를 바꾸려고 하면 안됨..!
  2. 너무 일찍 커밋을 한 경우(무언가 빼먹고 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

image



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로 남음

08-2

# 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)을 생성
  • 커밋 히스토리 변경 없이 해당 커밋 내용만을 삭제한 상태의 새로운 커밋을 생성

08-1



추가 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



정리

08-3

image



그외 방법

$ 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}



References

댓글남기기