Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발자공부일기

2024-10-31 본문

TIL(Today I Learned)

2024-10-31

JavaCPP 2024. 10. 31. 19:57

오늘 팀원과 협업중 깃허브를 업로드 하는중 오류메세지가 나왔는데 습관적으로 확인 누르듯 강제로 push해버렸다.

별 큰일은 없었지만 dev branch안의 모음폴더에 하나(기존에 있던 파일) 내가 실수로 강제push한 파일이 폴더 밖에 있었다. 그 때는 그냥 코드를 복사 붙여넣기로 수정하고 외부에 있던 파일을 삭제하며 해결했는데 나중에 알아보니 큰일이 날 수 있었던거 같다.

 

내가 Pull하지 않고 push를 하려해서 저런 상황이 발생했는데 Git의 입장에서는 최신화되지 않은 로컬의 코드를 모든 개발자가 공유하고 있는 Github의 코드에 push해서 덮어씌운다면 모두가 열심히 작업한 코드가 없어져버리는 최악의 상황이 발생할 수도 있기 때문이라고 한다.

 

변경사항이 있다면 무조건 pull하고 push하도록 하자.

 

dev 브랜치에서 작업한 후, GitHub의 main 브랜치에 있는 최신 코드를 pull하지 않고 push하려 하면 업스트림 브랜치(즉, 원격 저장소)와 로컬 브랜치 간의 커밋 히스토리가 일치하지 않아 충돌이 발생합니다.

충돌 발생: dev 브랜치가 main 브랜치의 최신 커밋과 일치하지 않아서 push가 거부됩니다. 이때 Git은 충돌을 방지하기 위해 다음과 같은 오류 메시지를 출력합니다.

error: failed to push some refs to '<repository-url>'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to integrate the remote changes (e.g.,
hint: 'git pull ...') before pushing again.

이 오류는 원격 main 브랜치에 새로운 커밋이 추가되었기 때문에 발생하며, 이를 해결하려면 main 브랜치의 최신 상태를 dev 브랜치에 반영해야 합니다.

 
 

해결 방법

git pull로 main의 최신 커밋을 dev에 병합하기

 

dev 브랜치에서 다음 명령어를 실행하여 main 브랜치의 최신 변경 사항을 가져오고, 그 후 다시 push 합니다.

 

 

git checkout dev
git pull origin main
git push origin dev

 

히스토리를 깔끔하게 유지하려면 rebase를 사용해, main 브랜치의 변경 사항을 dev 브랜치 커밋 전에 적용할 수 있습니다.

 

git pull --rebase로 히스토리 정리하기

git checkout dev
git pull --rebase origin main
git push origin dev

이 방법은 히스토리를 직선형으로 유지해 충돌을 최소화할 수 있습니다.

 

`git rebase`는 Git에서 브랜치의 커밋 히스토리를 변경하고 정리할 때 사용하는 명령어입니다. 다른 브랜치의 최신 커밋을 현재 브랜치에 적용하여 히스토리를 직선형으로 정리하는 방식이기 때문에, 협업 시 커밋 기록을 더 깔끔하게 만들 수 있습니다.

`rebase`의 주된 목적은 브랜치를 병합할 때 생기는 불필요한 커밋을 줄이고, 깔끔한 히스토리를 유지하는 것입니다.

 

 `rebase`의 작동 방식

1. 상황 `main` 브랜치와 `feature` 브랜치가 있고, `main` 브랜치에 커밋이 추가되었습니다.

main: A -- B -- C
feature: A -- B -- D -- E


   여기서 `main`에 커밋 `C`가 추가되었고, `feature`는 커밋 `D`, `E`가 있습니다. 

2. rebase 수행: `feature` 브랜치에서 `git rebase main`을 실행하면, `feature`의 히스토리가 `main`의 최신 상태를 기준으로 다시 적용됩니다.

main: A -- B -- C
feature (rebased): A -- B -- C -- D' -- E'


   여기서 `D'`와 `E'`는 새로 생성된 커밋으로, `main`의 최신 커밋 `C` 뒤에 붙게 됩니다.

rebase와 merge의 차이

- `merge`는 두 브랜치를 합칠 때 병합 커밋이 생성되며, 두 브랜치의 히스토리가 모두 보존됩니다.
- `rebase`는 히스토리를 직선형으로 정리하여, 마치 한 브랜치에서만 작업한 것처럼 보입니다.

주의사항

`rebase`는 공유된 커밋에는 사용하지 않는 것이 좋습니다. 이미 공유된 커밋을 `rebase`하면 다른 팀원과 히스토리가 달라져 충돌이 발생할 수 있습니다. `rebase`는 개인 작업을 정리하거나, 원격 저장소에 푸시하기 전에 히스토리를 깔끔하게 만드는 용도로 주로 사용합니다.

 

위 방법 중 하나로 main의 최신 커밋을 dev 브랜치에 반영한 후 push하면 문제가 해결됩니다.

 

 

만약 rebase없이 강제로 푸시하면 어떻게 될까?

rebase나 pull 없이 강제로 push하려면 --force 옵션을 사용해 강제로 push할 수 있습니다

git push --force origin dev

 

하지만 강제로 푸시하는 것은 주의가 필요합니다. 다음과 같은 결과가 발생할 수 있습니다.

강제 푸시의 영향

  1. 다른 커밋이 덮어씌워짐: 원격 저장소의 main 브랜치에는 dev 브랜치에 없는 새로운 커밋이 포함되어 있는데, 이를 무시하고 --force로 푸시하면 원격 main의 변경 사항이 dev 브랜치 커밋으로 덮어씌워집니다. 원격 저장소의 최신 기록이 사라져 다른 팀원들이 본 히스토리와 달라지며, 협업에 혼란을 줄 수 있습니다.
  2. 히스토리 충돌 발생: 강제 푸시 이후에 main의 덮어씌워진 커밋을 다른 팀원이 pull하게 되면 로컬 히스토리와 원격 히스토리가 달라져 충돌이 발생할 수 있습니다. 이로 인해 작업 내용이 손실되거나 충돌을 수동으로 해결해야 하는 상황이 생깁니다.

안전하게 강제 푸시하기 위한 방법

  • 로컬에서 미리 확인: 다른 작업자에게 영향을 줄 수 있으므로, rebase나 pull로 최신 커밋을 받아 충돌을 미리 해결한 뒤 푸시하는 것이 안전합니다.
  • 단독 작업 중인 브랜치에서만 사용: 혼자 사용하는 브랜치나 실수로 잘못 푸시한 브랜치를 되돌릴 때는 --force 푸시가 유용할 수 있지만, 협업 중인 브랜치에서는 가급적 피하는 것이 좋습니다.

 

 

'TIL(Today I Learned)' 카테고리의 다른 글

자바스크립트 기초 문법2  (0) 2024.11.04
자바스크립트 기초 문법(자료형)1  (0) 2024.11.01
2024-10-30  (0) 2024.10.30
2024-10-28  (0) 2024.10.28
2024-10-25  (0) 2024.10.25