git reset
commit 이력을 특정 상태로 되돌아가기 위해(rest) 사용되는 명령어
- repository, stage, working tree의 상태를 원하는 시점(or commit id)로 복원하는 데 사용하는 명령
- 단, commit history의 일부를 삭제하기 때문에 remote repository 를 통해 공동 작업자들이 있는 경우엔 revert 를 대신 사용해야함.
3가지 mode
git reset
은 다음과 같이 3가지 모드로 동작함.
--soft
: commit을 취소시킴.
- 최근 commit을 하기 전 상태로 돌아감.
- 즉, stage 상태까지 복원됨.(commit만 되돌림)→
add
가 이루어진 상태로 commit 하기 바로 직전 상태임.
--mixed
(default): commit과 staging을 취소시킴.
- 최근 commit과 staging을 하기 전 상태로 돌아감.
- stage 상태는 복원되지 않음. default. →
add
가 필요함.
--hard
: commit, staging, working tree변경 을 모두 취소시킴.
- 최근 commit, staging, 그리고 파일 변경을 하기전 상태로 돌아감.
- 즉,
--hard
인 경우, 파일등도 삭제됨. (주의할 것)
사용법
git reset [mode] [복원할_commit_id]
[mode]
:--soft
,--mixed
,--hard
중 하나임. (기본--mixed
)[복원할_commit_id]
: reset하고자 하는 commit의 hash 또는 reference.
사용례00
다음은 가장 최근에 수행한 commit을 취소시킴.
(git reset
은 commit까지 이루어진 변경사항을 취소시킬 때 사용됨)
git reset HEAD^
HEAD^
은 현재 commit인HEAD
의 바로 이전 commit을 가르킴.HEAD~1
은 현재 commit인HEAD
로부터 1번 전의 commit을 가르키므로HEAD^
와 같음.
기본으로 --mixed
로 수정되므로, 가장 최근의 commit에 대한 변경사항이 working tree에만 남아있고, repository와 stage에선 삭제된다.
사용례01
다음은 hash 3fd92e
가 가르키는 commit id 이후의 모든 commit history를 제거하고,
해당 commit id가 가르키는 상태로 repository, stage, working tree를 복원한다.
git reset --hard 3fd92e
주의 사항.
git reset
은 commit history 자체를 변경하기 때문에, 관련된 변경에 대한 모든 기록이 삭제됨.- 이는 remote repository를 통해 이전 commit history를 가지고 있는 공동작업자들에게 심각한 문제를 일으키게 된다.
- 때문에 remote repository를 통해 공동작업자가 있는 경우, 이전 commit으로 되돌리기 위해선
git revert
를 이용해야 함.
가급적 remote repository에 적용된 commit을 제거하는 reset은 사용해선 안된다.
2023.12.30 - [utils/git and github] - [git] revert : 특정 commit 취소하기.
참고: remote repository 에 reset 적용하기: git push origin main --force
--force
옵션을 통해 강제적으로 remote repository의 상태를 강제로 덮어쓸 수 있음.
remote repository의 history가 변경되기 때문에 매우 매우 신중하게 사용해야하고, 가급적 사용을 하지 않아야만 함.
(모든 팀원들과 충분히 상의 후 최후의 수단으로...)
- 기존의 commit history 중 일부가 완전히 삭제되는 작업이므로 충분히 인지하고 수행할 것.
- 다른 공동작업자에게 치명적인 문제를 낳을 수 있으므로 모든 작업자와 상의 후 수행해야함.
- 수행전 전체 내용을 백업하길 권함.
--force-with-lease
옵션을 대신 사용하길 권하는데,
이 옵션은 다른 작업자에 의한 update가 없는 상황에서만 강제 push가 수행되게 해주기 때문에 보다 실수를 줄여준다.
(즉, --force
를 사용하기 전 반드시 다른 작업자에 의한 update가 없어야 함을 의미함.)
Tutorial
1. 연습용 git repository 생성.
먼저, 연습용 directory로 이동하고, 해당 directory 를 git repository로 초기화:
cd git_tutorial_reset
git init
2. sample commits 수행.
reset
테스트를 위한 몇 가지 commit을 생성:
echo "Hello" > file.txt
git add file.txt
git commit -m "Initial commit"
echo "World" >> file.txt
git add file.txt
git commit -m "Second commit"
현재 commit history 를 다음으로 확인하면 위의 두 개의 commit이 보임:
git log --oneline
3. --soft
모드
--soft
모드는 HEAD 포인터만 이전 commit (HEAD~1
or HEAD^
)으로 복원하고
stage와 working tree는 그대로 보전:
git reset --soft HEAD~1
이 명령을 실행하면
- 마지막 commit은
commit log
에서 제거된 것을 확인할 수 있음 :git status
로 확인할 것. - 하지만, 변경 내용은 여전히 stage에 남아있음.
4. 다른 테스트를 위한 commit
git commit -m "New Second commit"
위의 명령을 실행시, 현재 stage 의 내용이 repository에 commit 됨.
5. --mixed
모드
다음은 --mixed
모드로 HEAD
포인터를 이전 commit으로 이동시키고, stage를 초기화하지만, working tree에 변경사항을 그대로 보존하게 됨:
git reset --mixed HEAD~1
이 명령을 실행하면 마지막 commit이 사라지고, 변경 내용은 stage에서 제거되지만 여전히 working tree에 남아있습니다.
6. 다른 테스트를 위한 add와 commit
git add .
git commit -m "New New Second commit"
7. --hard
모드
--hard
모드는 HEAD 포인터, stage, 그리고 working tree 모두를 이전 commit 상태로 복원(변경사항이 완전히 제거됨):
git reset --hard HEAD~1
이 명령을 실행하면 마지막 commit을 포함하여 해당 변경 내용이 완전히 제거됨.
8. 특정 커밋으로 리셋하기
특정 commit hash를 사용하여 reset을 실행할 수 있음:
git reset --hard <commit-hash>
<commit-hash>
는 git log
로 확인한 커밋 해시입니다.
9. 실수로 --hard
리셋했을 때 되돌리기 (advanced)
만약 실수로 --hard
리셋을 실행했다면, git reflog
를 사용하여 이전 상태로 되돌릴 수 있음:
git reflog
git reset --hard <reflog-commit-hash>
<reflog-commit-hash>
는 reflog로 확인한 이전 commit hash임.
10. remote repository와의 작업을 위한 튜토리얼 부분 시작.
--force
option을 테스트하기 위해 remote repository로 연결.
git remote add origin [url_of_remote_repository]
git branch -M main
git push -u origin main
11. 테스트를 위한 작업
추가적인 commit 을 생성하고 이를 remote repository에 push.
echo "Hi" >> file.txt
git add .
git commit -m "Third commit"
echo "Korea" >> file.txt
git commit -am "Fourth commit"
git push
12. local repository를 reset!
반드시 팀원들과 충분한 상의를 하고, 다른 충돌이 나지 않도록 정리한 후 해야한다.
git reset --hard HEAD~2
- 이 명령은 HEAD를 두 개의 커밋 이전으로 이동시키고, 해당 커밋들을 작업 디렉토리와 스테이징 영역에서 제거함.
13. --force
옵션으로 강제 push
remote repository 에 변경 사항을 강제로 push
: --force
옵션을 사용
git push origin main --force
origin
은 remote repository의 alias이고,main
은 branch의 이름
--force-with-lease
옵션을 사용하면,
다른 사용자가 remote repository를 update하지 않은 경우에만 강제 push가 이루어짐.--force
보다 권장되는 방식임.
참고로 --force
옵션 없이 push
할 경우, 다음과 같이 거절됨.
❯ git push
Enter passphrase for key '/Users/dsaint31/.ssh/id_ed25519':
To github.com:dsaint31x/git_tutorial_reset.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:dsaint31x/git_tutorial_reset.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.
'utils > git and github' 카테고리의 다른 글
[Git] merge: branch를 합침 (0) | 2024.05.26 |
---|---|
[Git] git 에서 branch란? (0) | 2024.05.26 |
[Git] mv (0) | 2024.05.21 |
[Git] rm (0) | 2024.05.21 |
[Git] git 설치 후 우선 해줘야 하는 작업들 (0) | 2024.05.21 |