피쳐 브랜치 리베이스 후 Git 푸시 거부


918

좋아, 나는 이것이 간단한 자식 시나리오라고 생각했다.

나는이 master지점과 feature지점을. 나는 몇 가지 작업을하고 master, 어떤 작업은 계속하고 , feature더 작업을 master합니다. 나는 이런 식으로 끝납니다 (사전 순서는 커밋 순서를 암시합니다).

A--B--C------F--G  (master)
       \    
        D--E  (feature)

git push origin master원격 작업을 master업데이트하거나 git push origin feature(켜져있을 때 feature) feature작업에 대한 원격 백업을 유지하는 데 아무런 문제가 없습니다 . 지금까지 우린 잘 지내

하지만 지금은 리베이스 할 feature의 상단에 F--G, 마스터에 커밋 I 있도록 git checkout feature하고 git rebase master. 여전히 좋은. 이제 우리는 :

A--B--C------F--G  (master)
                 \
                  D'--E'  (feature)

문제 : 백업 내가 원하는 순간 새로운 리베이스 feature로 분기 git push origin feature, 푸시가 거부 트리가 리베이스로 인해 변경되었습니다 때문이다. 이 문제는로만 해결할 수 있습니다 git push --force origin feature.

나는 --force그것을 확신하지 않고 사용하는 것을 싫어 한다. 그래서 필요합니까? 리베이스는 반드시 다음 push이 충만 해야 함을 의미 합니까 --force?

이 기능 브랜치는 다른 개발자와 공유되지 않으므로 강제 푸시에 실제로 아무런 문제가 없으며 데이터를 잃지 않을 것입니다. 질문은 더 개념적입니다.

답변:


681

문제는 git push원격 브랜치가 로컬 브랜치로 빨리 전달 될 수 있다고 가정한다는 것입니다. 즉, 로컬 브랜치와 원격 브랜치의 모든 차이점은 끝에 새로운 커밋이있는 로컬에 있다는 것입니다.

Z--X--R         <- origin/some-branch (can be fast-forwarded to Y commit)
       \        
        T--Y    <- some-branch

git rebase커밋 을 수행 하면 D와 E가 새 기본에 적용되고 새 커밋이 생성됩니다. 그것은 rebase 후 당신은 다음과 같은 것을 의미합니다 :

A--B--C------F--G--D'--E'   <- feature-branch
       \  
        D--E                <- origin/feature-branch

이 상황에서 원격 지점은 로컬로 빨리 전달 될 수 없습니다. 이론적으로 로컬 브랜치는 원격으로 병합 할 수 있지만 (이 경우 필요하지 않음) git push빨리 감기 병합 만 수행하면 throw 및 오류가 발생합니다.

그리고 --force옵션은 원격 브랜치의 상태를 무시하고 커밋으로 설정하는 것입니다. 따라서 git push --force origin feature-branch단순히 origin/feature-branchlocal로 재정의하십시오 feature-branch.

내 의견으로는, master당신이 그 지점에서 일하는 유일한 사람이라면 기능 브랜치를 rebasing 하고 원격 리포지토리로 강제 푸시하는 것은 괜찮습니다.


67
솔직히 말해서, 원래 버전의 피쳐 브랜치를 끌어서 하나의 기반으로 병합하면 리베이스의 전체 아이디어가 제거됩니다.
KL-7

24
어쩌면 나는 당신을 올바르게 이해하지 못했지만 기능 지점을 가져 와서 새로운 마스터 지점으로 리베이스하면 기능 버전의 원격 버전을 새 버전으로 빨리 전달할 수 없으므로 강제로 다시 밀어 넣을 수 없습니다 기능 분기의 (기반) 버전. 이것이 바로 OP가 그의 질문에 묘사 한 것입니다. 리베이스 한 후 푸시하기 전에이 git pull feature-branch풀은 (기능 브랜치의 원격 및 로컬 버전을 병합하여) 새로운 병합 커밋을 생성합니다. 리베이스 후 불필요한 병합을 얻거나을 사용하여 푸시합니다 --force.
KL-7

6
아, 알았어요 Mark Longair의 답변과 동일한 접근 방식을 설명하고 있습니다. 그러나 병합 커밋을 생성합니다. 경우에 따라 유용 할 수도 있지만 push --force병합 커밋없이 커밋 기록을 선형으로 유지하기 위해 주로 자체 기능 분기에서 리베이스를 사용하므로 문제가 아닙니다.
KL-7

11
“force-push”의 문제점은 실제로 어떤 버전 제어 시스템에서도 가능하지 않은“실제로 잃어버린”(사전 커밋)이 가능하다는 것입니다. 강제 손상을 허용하지 않도록 설정하여 잠재적 인 손상을 제한합니다. (심지어 / 해고 된 직원, 자신의 관용구, 피곤하고 과로 한 '의사 결정'...).
Frank Nocke

13
--force-with-lease@hardev가 제안한 것처럼 훌륭한 옵션입니다
augustorsouza

465

-f 또는 --force를 사용하는 대신 개발자는

--force-with-lease

왜? 원격 지사에서 변경 사항을 확인하기 때문에 좋은 아이디어입니다. James와 Lisa가 동일한 기능 지점에서 작업 중이고 Lisa가 커밋을 추진했다고 가정 해 봅시다. 제임스는 이제 자신의 지사를 리베이스하고 푸시하려고 할 때 거부됩니다. 물론 James는 이것이 rebase에 의한 것으로 생각하고 --force를 사용하며 Lisa의 모든 변경 사항을 다시 작성합니다. 야고보가-임대를 사용했다면 다른 사람이 저지른 일이 있다는 경고를 받았을 것입니다. 리베이스를 추진할 때 누군가가 --force-with-lease 대신 --force를 사용하는 이유를 알 수 없습니다.


33
좋은 설명입니다. git push --force-with-lease나에게 무리를 구했다.
ckib16

5
유용한 의견이지만 질문에 대한 답변은 아닙니다.
Dallin

4
이것이 마스터 / 개발에 기반을 둔 문제를 야기하는 해답입니다. 이것이 바로 --force-with-lease가 존재하는 이유입니다.
Tamir Daniely

3
이것이 정답입니다. 다른 사람이 그 동안 저지른 경우 강제로 밀지 않고 설명 된 문제를 정확하게 해결합니다.
Luzian

3
나는 받아 들여진 대답과 이것이 하나의 문제를 다룬다 고 생각합니다. 수락 된 답변은 왜 강제해야하는지 설명합니다. 그리고 이것은 왜 --force-with-lease사용의 문제를 해결 하는지 설명합니다--force
Jeff Appareti

47

대신 "checkout -b"를 사용하면 이해하기 쉽습니다.

git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature

삭제하면 다른 SHA ID가 포함 된 종료 분기를 푸시하지 못합니다. 이 경우 원격 지점 만 삭제하고 있습니다.


6
특히 팀에 모든 git push --force 명령을 거부하는 git hook이있는 경우 효과적입니다.
Ryan Thames

1
잘 작동 해 주셔서 감사합니다. 내가 더 잘 이해하기 위해 읽은 자세한 내용은 다음과 같습니다. 강제 푸시를 원하지 않거나 할 수 없을 때 매우 유용합니다. 원격 지점을 삭제 하고 리베이스
RajKon

5
이것과 같은 결과를 push --force가지기 때문에 git repo prevent를 피할 수있는 방법 일뿐 --force입니다. 따라서, 나는 이것이 좋은 아이디어라고 생각하지 않습니다-repo가 ​​허용 push --force하거나 정당한 이유로 그것을 비활성화합니다. --force다른 개발자의 커밋을 잃거나 다른 문제를 일으킬 위험이 없으므로 원격 저장소에서 비활성화 하면 Nabi의 대답이 더 적합합니다 .
Logan Pickup

19

이에 대한 한 가지 해결책은 msysGit의 rebasing merge 스크립트가 수행하는 작업을 수행하는 것입니다 . rebase 후에 는와 feature함께 이전 헤드를 병합합니다 -s ours. 커밋 그래프로 끝납니다.

A--B--C------F--G (master)
       \         \
        \         D'--E' (feature)
         \           /
          \       --
           \    /
            D--E (old-feature)

... 그리고 당신의 푸시 feature는 빨리 진행될 것입니다.

다시 말해, 다음을 수행 할 수 있습니다.

git checkout feature
git branch old-feature
git rebase master
git merge -s ours old-feature
git push origin feature

(테스트되지는 않았지만 맞습니다.)


26
기능 지점으로 다시 git rebase병합하는 대신 사용하는 가장 일반적인 이유 master는 깨끗한 선형 커밋 기록을 만드는 것입니다. 당신의 접근 방식으로 커밋 역사는 더욱 악화됩니다. 그리고 rebasing은 이전 버전에 대한 참조없이 새로운 커밋을 생성 하므로이 병합의 결과가 적절한 지 확실하지 않습니다.
KL-7

6
@ KL-7 : 요점은 merge -s ours인위적으로 이전 버전에 대한 부모 참조를 추가한다는 것입니다. 물론, 역사는 깨끗해 보이지 않지만, 문제는 feature지점 의 추진을 강요함으로써 특히 귀찮은 것 같습니다 . 당신이 리베이스를 원한다면, 그것은 어느 하나입니다. :) 더 일반적으로, 나는 msysgit 프로젝트가 이것을하는 것이 흥미 롭다고 생각한다 ....
Mark Longair

@ KL-7 : 우연히, 나는 당신의 대답을 +1했습니다. 이것은 분명히 옳은 것입니다.
Mark Longair

적어도 저에게는 흥미 롭습니다. 감사합니다. 나는 본 적이 ours전에 전략을하지만 자동으로 우리 지점의 변화를 이용하여 이러한 문제를 해결하기 만 충돌 상황에 적용 생각했다. 다르게 작동한다는 것이 밝혀졌습니다. 그런 식으로 작업하면 rebased 버전 (예 : repo 관리자가 깨끗하게 적용해야 함 master)이 필요하지만 강제 추진을 피하고 싶을 때 (어떤 이유로 많은 ppl이 기능 분기를 사용 하는 경우) 매우 유용합니다 .
KL-7

15

이 브랜치에는 개발자가 한 명만있을 수도 있고 그렇지 않을 수도 있습니다. 즉, 현재 (리베이스 후) 원점 / 기능과 인라인되지 않습니다.

따라서 다음 순서를 사용하는 것이 좋습니다.

git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2

예, 새로운 브랜치, 이것은 --force없이 이것을 해결해야합니다. 일반적으로 주요 git 단점이라고 생각합니다.


3
죄송 합니다만 : 기존 분기를 재정의하는 것을 피하기위한“지사 생성 유지”는“독점 개발자”(재정의 할 수있는) 나 기능 분기에서 일하는 여러 사람 (지사에“증가”의사 소통을해야 함)에 도움이되지 않습니다 이동하기 위해). — 버전 관리 시스템에서 수동 버전 관리 (“thesis_00.doc, thesis_01.doc, ...”)와
비슷

2
또한 이것은 하나의 지점 이름으로 github PR을 열었을 때 도움이되지 않습니다. 푸시 한 새로운 지점 이름에 대한 새로운 PR을 만들어야합니다.
gprasant

1
@frankee Half 내 경험으로는 사실입니다. 외로움을 느끼는 개발자의 경우, 강제로 밀기 만하면되지만 나중에 물릴 수도 있습니다. + 새로운 개발자가 방금 가입 했습니까? 아니면 --hard reset을 사용하지 않는 일부 CI 시스템일까요? 팀 공동 작업의 경우 새 지점 이름을 전달하는 것이 충분히 쉽다고 생각합니다. 팀을 위해 쉽게 스크립팅 할 수 있습니다. 팀을 위해 로컬로 리베이스하거나 지점을 병합 할 준비가되면 매일 작업하지 않는 것이 좋습니다. 추가 커밋은 결과적으로 rebase / merge 충돌을 처리하는 것보다 문제가 적습니다.
JAR.JAR.beans

PR에 대한 @gprasant, 다시 말하지만, 이것은 rebase하기에 잘못이라고 생각합니다. 실제로 PR 수정 사항으로 단일 커밋을보고 싶습니다. 리베이스 (스쿼시)는 마스터와의 병합의 일부로서 그리고 PR이 모두 완료되고 준비 될 때만 발생해야합니다 (따라서 새로운 PR을 열 필요가 없습니다).
JAR.JAR.beans

13

강제 추진을 피하는 나의 방법은 새로운 브랜치를 만들고 그 새로운 브랜치에 대한 작업을 계속하고 약간의 안정성을 유지 한 후에 리베이스 된 이전 브랜치를 제거하는 것입니다.

  • 체크 아웃 한 분기를 로컬로 리베이스
  • 재 기반 지점에서 새 지점으로 분기
  • 해당 지점을 새 지점으로 원격으로 푸시합니다. 원격에서 이전 분기를 삭제

1
왜이 옵션을 좋아하지 않습니까? 가장 깨끗하고 단순하며 안전합니다.
cdmo

지점 이름을 추적하는 약 200 개의 시스템이 있고 작업의 특정 이름이어야하고 지점 이름 바꾸기를 시작할 때마다 푸시 할 때마다 마음이 풀립니다.
Tamir Daniely

@TamirDaniely 시도하지 않았지만 동일한 이전 이름으로 새 분기를 밀고 밀기 전에 (원격에서) 이전 분기를 삭제하면 문제가 해결됩니까?
Nabi

2
@Nabi --force-with-lease가하는 일은 정확히 당신의 것이 아닌 새로운 커밋이 없다는 것을 확인하는 것입니다.
Tamir Daniely

12

다른 사람들이 귀하의 질문에 답변했습니다. 브랜치를 리베이스하면 해당 브랜치를 강제로 밀어야합니다.

Rebase 및 공유 저장소는 일반적으로 작동하지 않습니다. 이것은 역사를 다시 쓰고있다. 다른 사람이 해당 지점을 사용 중이거나 해당 지점에서 분기 한 경우 리베이스는 매우 불쾌합니다.

일반적으로 rebase는 로컬 지점 관리에 적합합니다. 원격 지점 관리는 명시 적 병합 (--no-ff)과 함께 가장 잘 작동합니다.

또한 마스터를 기능 분기에 병합하지 않습니다. 대신 마스터로 리베이스하지만 새 분기 이름 (예 : 버전 접미사 추가)으로 리베이스하십시오. 이것은 공유 리포지토리에서 rebasing하는 문제를 피합니다.


5
예를 추가해 주시겠습니까?
Thermech

8

지점 git merge master에 어떤 문제가 feature있습니까? 그러면 메인 라인과 분리 된 상태로 유지 한 작업이 보존됩니다.

A--B--C------F--G
       \         \
        D--E------H

편집 : 아 죄송합니다 문제 설명을 읽지 못했습니다. 을 수행 할 때 힘이 필요합니다 rebase. 기록을 수정하는 모든 명령에는 --force인수 가 필요합니다 . 이것은 당신이 일을 잃는 것을 막기위한 비상 안전 장치입니다 (오래 D되고 E잃어 버릴 것입니다).

그래서 당신은 수행 git rebase(부분적으로 숨겨진 없지만 같은 나무 모양을 만들어하는 DE더 이상 명명 된 지점에 있습니다)를 :

A--B--C------F--G
       \         \
        D--E      D'--E'

그래서, 당신의 새로운 추진하려고 할 때 feature와 (지점 D'E' 그것에), 당신은 잃게 D하고 E.


3
그것에 아무런 문제가 없으며 작동한다는 것을 알고 있습니다. 그것은 내가 필요한 것이 아닙니다. 내가 말했듯이, 문제는 실용적보다 더 개념적입니다.
유발 아담

4

나를 위해 쉬운 단계를 수행하십시오.

1. git checkout myFeature
2. git rebase master
3. git push --force-with-lease
4. git branch -f master HEAD
5. git checkout master
6. git pull

위의 모든 작업을 수행 한 후 다음 명령으로 myFeature 분기를 삭제할 수 있습니다.

git push origin --delete myFeature

3

다음은 나를 위해 작동합니다.

git push -f origin branch_name

내 코드를 제거하지 않습니다.

그러나 이것을 피하려면 다음을 수행하십시오.

git checkout master
git pull --rebase
git checkout -b new_branch_name

새 지점에 대한 커밋을 모두 선택할 수 있습니다. git cherry-pick COMMIT ID 새 지점을 밀어 넣으십시오.


5
-f의 별칭이며 --force, 가능하면 질문에서 피하려고하는 것입니다.
epochengine

1

OP가 문제를 이해하면 더 좋은 해결책을 찾으십시오 ...

이것은 연습으로 어떻습니까?

  • 실제 기능 개발 브랜치에 참여하십시오 (리베이스 및 강제 푸시하지 않으므로 동료 기능 개발자는 당신을 미워하지 않습니다). 여기에서 main으로 변경 사항을 정기적으로 병합하십시오. 메시에의 역사 는 그렇습니다. 그러나 인생은 쉽지 않으며 아무도 그의 일에 관여하지 않습니다.

  • 하나의 기능 팀 구성원이 정기적으로 모든 기능 커밋을 실제로 재기 반화하고 강제로 푸시 하는 두 번째 기능 개발 브랜치를 보유하십시오 . 따라서 거의 최근의 마스터 커밋을 기반으로 거의 깨끗합니다. 기능이 완료되면 해당 분기를 마스터 위로 밉니다.

이 메소드의 패턴 이름이 이미있을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.