![[GIT] git pull 시 merge 오류 발생했을 때 강제로 덮어쓰는 방법, git fetch, reset, pull](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmV1FB%2Fbtrl4LHRm6D%2FLTnh8iJIexwFxhCo2mVTs1%2Fimg.png)
상황
1. 캡스톤 디자인 개발을 진행하면서 AWS EC2 서버를 이용해 API 서버를 배포하는 중이다.
2. Github를 통해 변경된 코드를 서버에 옮기고 있다.
3. 이전에 있던 코드와 충돌이 발생하면서 다음과 같은 에러가 발생한다.
git fetch 명령어를 통해서 커밋을 가져온 후, merge하면 해결할 수 있다.
하지만, Github에서 가져오려는 코드가 어떤 것인지, 이전 코드와 어떻게 다른지 확실히 알고 있기 때문에 이전 코드와 상관없이 Github에 있는 코드를 pull 명령어를 통해서 강제로 덮어씌우고 싶다.
2025-01-22 Updated
학생 때 진행한 사이드 프로젝트라 이런 결정을 했지만, 지금은 절대 안할 선택인 것 같습니다.
개발 전 최신 버전으로 pull을 습관화하고, 브랜치를 적절히 나눠서 충돌이 나는 상황을 피하는 것이 최선인 것 같습니다.
해결 방법
해결 방법은 Repository에서 최신 커밋 정보를 가져와서 강제로 HEAD를 옮긴 후 저장하는 것입니다.
1. git pull을 하기 위해서 깃허브의 repository에서 커밋 정보를 확인합니다.
$git fetch --all
--all 옵션을 통해 모든 정보를 확인합니다.
2. git reset을 통해 head를 최신 커밋을 가리키게 합니다.
$git reset --hard origin/master
--hard 옵션은 강제로 head를 옮기는 것입니다. 이런 옵션들을 사용할 때는 신중할 필요가 있습니다.
3. git pull을 통해 가져온 정보를 저장합니다.
$git pull
이전 코드와 상관 없이 최신 커밋을 덮어 씌우는 것입니다.
git push --force-with-lease (2025-01-22 Updated)
여러 사람들과 함께 개발하는 Repository에 강제로 무언가를 한다는 것은 재앙이 될 수 있습니다.
누군가의 작업 내용이 덮어쓸 수도 있고, 심지어 본인의 작업 내용마저 덮어버릴 수 있습니다. (Ex. Github의 README..)
환경에 따라서는 CI/CD 파이프라인에 따라 영향도가 더욱 커질 수도 있겠지요.
--force-with-lease 옵션은 최소한 다른 커밋 내역을 덮어쓰지 않도록 해주는 옵션입니다. 해당 옵션을 사용하면 다음과 같이 동작합니다.
1. 원격 저장소의 상태를 확인한다. (git fetch)
2. 로컬 브랜치가 최신 상태를 기준으로 작업되었는지 확인한다. (Commit ID 확인)
3. 만약, 변경 사항이 있다면 에러를 반환한다.
커밋된 다른 내용이 있는지 먼저 확인하기 때문에, 다른 사람의 커밋 내용을 덮는 것은 방지하는 것입니다.
다른 사람의 커밋을 덮어쓰지 않으니, 만약 문제가 생겨도 이 커밋에 대해서만 롤백하면 되니까 복구도 훨씬 간편해집니다.
주의 사항
원격 저장소의 상태를 확인하는 것은 fetch 명령어와 동일하게 동작합니다. 즉, 추적 브랜치를 로컬에서 확인하는 것입니다.
그래서, git fetch를 하고 push --force-with-lease를 하게 되면 그대로 덮어씌우게 됩니다.
세부 사항
git fetch
$git fetch는 원격 저장소(Github)에 있는 정보들을 가져오는 명령어입니다. 어떤 변화가 있는지 확인할 수 있습니다. 정보를 저장하는 것은 아니고, 정보를 확인하고 필요하면 병합(merge)할 수 있습니다. fetch를 사용해서 최신 커밋 정보를 가져오면 FETCH_HEAD라는 브랜치로 가져옵니다. 따라서, 커밋 정보를 보기 위해서는 해당 브랜치로 이동(checkout)해야합니다.
이렇게 최신 커밋 정보를 가져와서 정보를 저장하려면(합치려면) $git pull을 사용해도 되고, $git merge를 사용해도 됩니다.
git reset
$git reset은 HEAD의 포인터를 특정 위치로 옮기는 명령어입니다.
--hard 옵션을 추가해서 이전 커밋으로 돌아가면, 그 커밋 이후에 내용들은 삭제됩니다.
--mixed 옵션을 추가해서 커밋을 이동하면 변경 이력이 모두 삭제되지만 스테이지에 코드가 남아있습니다. 이 코드를 add 후 커밋하면 됩니다.
--soft 옵션을 추가하면 mixed 옵션과 같지만 이미 스테이징 되어있습니다. 이 말은, add 없이 바로 커밋하면 된다는 뜻입니다.
이 명령어는 commit history를 덮어 씌우는 commit history로 바꾸기 때문에 기록이 없어집니다. 이 경우 다른 사람과 협업하는 상황에서 문제를 일으킬 수 있는 여지가 있습니다. 지금 제 상황과 같이 코드에 대한 확신이 있는 경우나 혼자 사용하는 브랜치에만 사용하는 것이 좋습니다.
정리
강제로 덮어쓰는 방법보다는 기존 코드와 잘 병합될 수 있도록 코드를 짜는 것에 신경을 쓸 필요가 있다고 생각했습니다.
'DevOps > GIT & GITHUB' 카테고리의 다른 글
[GIT] git bash 관리자 권한으로 실행하기 (0) | 2021.09.06 |
---|---|
GIT 제대로 활용하기! - branch (0) | 2021.02.13 |
본격적으로 GITHUB 사용하기! - remote, push, pull, fetch (0) | 2021.02.10 |
GIT을 이용한 버전관리 - 생성, 스테이지와 커밋, 커밋 되돌리기 (0) | 2021.02.08 |
GIT을 위한 간단한 리눅스 명령어 모음 (0) | 2021.02.08 |