리베이스 후 지점으로 밀 수 없습니다


131

우리는 git을 사용하고 마스터 브랜치와 개발자 브랜치를 가지고 있습니다. 새 기능을 추가 한 다음 커밋을 마스터로 리베이스 한 다음 마스터를 CI 서버로 푸시해야합니다.

문제는 리베이스 중에 충돌이 발생하면 리베이스가 완료된 후 원격 분기를 당길 때까지 원격 개발자 분기 (Github에서)를 푸시 할 수 없다는 것입니다. 중복 커밋이 발생합니다. 충돌이 없으면 예상대로 작동합니다.

질문 : rebase 및 충돌 해결 후 중복 커밋을 만들지 않고 로컬 및 원격 개발자 분기를 어떻게 동기화합니까?

설정:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

편집하다

따라서 다음과 같이 들리므로 워크 플로가 중단됩니다.

myNewFeature 작업 개발자 1 hisNewFeature 작업 개발자 2 모두 마스터를 기본 지점으로 사용

developer2는 myNewFeature를 hisNewFeature로 병합합니다.

developer1은 리베이스하고 충돌을 해결 한 다음 myNewFeature의 원격 지점으로 강제 푸시합니다.

며칠 후 developer2는 myNewFeature를 hisNewFeature에 다시 병합합니다.

이로 인해 다른 개발자가 developer1을 싫어합니까?


해결책이 아니라 생각입니다. 누구야 we? 당신은 당신보다 더 많은 팀에 있습니까? they코드를 공유하는 경우보다 사용하지 말아야한다고 말합니다 (내가 아는 사람들) rebase. 왜 그냥 안하고 git pullgit merge?
AdamT

죄송합니다, 우리 = 개발팀
Matt

1
그렇습니다. 코드를 공유 할 때 rebasing해서는 안됩니다. 그러면 아래에 나와있는 것과 같은 일을해야 할 수도 있습니다. ( forcePush)
AdamT

그들이 말할 때 미안 오 rewriting history, 그건입니다rebase
AdamT

그는 자신의 개발 지점을 말했듯이 누군가가 그것을 합병시킬 것으로 예상되지 않는 한 문제가되지 않아야한다.
Learath2

답변:


93

먼저, 귀하와 함께 일하는 사람들은 주제 / 개발 지점이 공유 개발을위한 것인지 아니면 자신 만의 것인지를 동의해야합니다. 다른 개발자들은 언제라도 리베이스되기 때문에 개발 지점에 합병하지 않는 것을 알고 있습니다. 일반적으로 워크 플로는 다음과 같습니다.

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

그런 다음 원격으로 최신 상태를 유지하려면 다음을 수행하십시오.

 git fetch origin
 git checkout master
 git merge --ff origin/master

나는 두 가지 이유로 이것을한다. 먼저 내 개발 지점에서 전환 할 필요없이 원격 변경 사항이 있는지 확인할 수 있기 때문입니다. 둘째, 예약되지 않은 / 커밋 된 변경 사항을 덮어 쓰지 않도록하는 안전 메커니즘입니다. 또한 마스터 브랜치로 빨리 병합 할 수없는 경우 누군가 원격 마스터를 리베이스했거나 (심하게 채울 필요가있는) 마스터를 실수로 마스터하여 내 목표를 정리해야 함을 의미합니다.

그런 다음 원격에 변경 사항이 있고 최신으로 빨리 전달하면 rebase 할 것입니다.

git checkout devel0
git rebase master
git push -f origin devel0

그런 다음 다른 개발자는 최신 브랜치에서 devel 브랜치를 리베이스해야한다는 것을 알고 있습니다.

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

훨씬 더 깨끗한 기록을 얻습니다.

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

당신의 변덕에 커밋을 앞뒤로 병합 하지 마십시오 . 중복 커밋을 생성하고 기록을 따르지 못하게 할뿐만 아니라 특정 변경으로 인한 회귀를 찾는 것이 거의 불가능 해집니다 (처음에 버전 제어를 사용하는 이유는 무엇입니까?). 당신이 겪고있는 문제는이 작업을 수행 한 결과입니다.

또한 다른 개발자가 귀하의 개발 지점에 커밋하는 것처럼 들립니다. 이것을 확인할 수 있습니까?

병합 할 수있는 유일한 시간은 주제 분기가에 승인 될 때 master입니다.

부수적으로. 여러 개발자가 동일한 저장소에 커밋하는 경우 개발자와 브랜치를 구분하기 위해 명명 된 브랜치를 갖는 것을 고려해야합니다. 예를 들면 다음과 같습니다.

git branch 'my-name/devel-branch'

따라서 모든 개발자 토픽 브랜치는 자체 중첩 세트 내에 있습니다.


1
"또한 다른 개발자들이 귀하의 개발 부서에 커밋하는 것처럼 들립니다.이를 확인할 수 있습니까?" 그렇습니다.
Matt

당신은 또한 또 다른 문제를 주목했습니다. 사무실과 집 사이에서 일하기. 나는 두 곳에서 합병을하고 하루가 끝날 때 나는 내가 멈춘 곳에서 데리러 갈 수있게한다. 그런 다음 리베이스 할 때 모든 커밋은 혼란을 초래합니다. 내 지점을 하나의 지점으로 취급하고 리베이스해야합니다.
Matt

@ 매트 그래, 그 두 가지 문제는 실제로 당신의 작업 흐름을 망칠 것입니다. 첫 번째로, 소유자 만이 지정된 분기 (예 : 'matt / devel')에 커밋 할 수 있다고 다른 개발자와 통신합니다. IMHO, 두 개발자는 어쨌든 같은 지점에 헌신해서는 안됩니다. 혼란을 만듭니다. 나중에 rebasing과 force push는 두 위치를 최신 상태로 유지해야합니다.
Trevor Norris

좋은 대답입니다. 부차적 인 질문이 있습니다. 왜 --force할 때 플래그 를 사용 합니까 git push -f origin devel0?
Nobita

2
@Nobita git push빨리 감기를 수행 할 수없는 경우 (즉, Sha 이력이 일치하지 않는 경우) 푸시를하여 이전 이력을에서 생성 된 새 이력으로 덮어 써야합니다 git rebase.
Trevor Norris

50

커밋을 더 아래로 움직일 때 푸시를 강제해야합니다 .git git은 분기 끝에 커밋을 추가 할 것으로 예상합니다. git push -f origin myNewFeature문제를 해결합니다.

팁 : 위의 합법적 인 힘 사용입니다. 공개적으로 액세스 가능한 저장소에 기록을 다시 쓰지 마십시오. 그렇지 않으면 많은 사람들이 당신을 미워할 것입니다.


1
워크 플로를 유지하는 가장 최적의 방법이라고 생각합니다.
Syed Priom

1
고마워 친구 이 명령을 사용하여 리베이스 된 로컬 브랜치를 동일한 원격 브랜치로 강제했습니다.
wei

11
사용하는 git push --force-with-lease것이 사용 하는 것보다 훨씬 안전합니다git push --force

git push --force-with-lease origin HEAD-당신의 목표 지점이 이미 체크 아웃되었다고 가정
Lucaci Sergiu

31

여기서 명심해야 할 가장 중요한 것은 풀과 리베이스가 무대 뒤에서하는 일입니다.

풀은 기본적으로 페치 및 병합의 두 가지 작업을 수행합니다. --rebase를 포함하면 병합 대신 rebase가 수행됩니다.

리베이스는 브랜치 이후 모든 로컬 변경 사항을 숨기고 브랜치를 대상의 최신 커밋으로 빨리 전달하고 변경 사항을 순서대로 해제하는 것과 거의 같습니다.

(이것은 리베이스를 수행 할 때 여러 충돌 해결 프롬프트와 병합으로 얻을 수있는 하나의 충돌 해결을 표시하는 이유를 설명합니다. 커밋을 보존하기 위해 리베이스되는 각 커밋에 대한 충돌을 해결할 수있는 기회가 있습니다. )

히스토리를 다시 작성하므로 원격 브랜치에 리베이스 된 변경 사항을 푸시하지 않으려 고합니다. 거의 항상 예외가 있기 때문에 Ofcoarse, 결코 조금 강하지 않습니다. 예를 들어 특정 환경에서 작동하기 위해 로컬 버전의 로컬 저장소를 유지해야하는 경우입니다.

강제로 다음 중 하나를 사용하여 리베이스 된 변경 사항을 푸시해야합니다.

git push -f origin newfeature

또는 경우에 따라 관리자가 강제 실행 기능을 제거하여 삭제하고 다시 작성해야합니다.

git push origin :newfeature
git push origin newfeature

어느 경우 에나 다른 지사가 원격 지사에서 귀하와 공동 작업하는 경우 수행중인 작업을 완전히 알고 있어야합니다. 이는 처음에 병합을 사용하여 작업하고 작업 분기를 마스터하고 제거하기 직전에 관리 가능한 커밋 형식으로 리베이스합니다.

거의 항상 git의 GC를 대체 할 수 있음을 기억하십시오.

git reflog

모든 리베이스 / 충돌 관리에서 길을 잃었을 때 더 안정적인 상태로 다시 재설정 할 수 있기 때문에 이것은 거대한 생명의 은인입니다.


위의 삭제 및 다시 작성 옵션이 훌륭하게 작동했습니다. 내 레포에 강요가 허용되지 않습니다!
Simon Holmes

2

강제 푸시를 수행해야합니다. 즉 git push -f origin myNewFeature

아, 그리고 당신은 사람들이 당신의 dev 브랜치를 기반으로하지 않는지 확인하는 것이 좋습니다. 일반적으로 히스토리를 전혀 다시 쓰지 않는 지점을 게시하지 않아야합니다 (또는 게시 된 히스토리를 다시 쓰지 마십시오). 한 가지 방법은 지점 이름과 같은 지점 이름을 사용하고 지점 이 때때로 마스터하도록 리베이스 될 것이라고 wip/myNewFeature언급하는 wip것입니다.


사용하는 git push --force-with-lease것이 사용 하는 것보다 훨씬 안전합니다git push --force

@MrCholo 사람들은 git이 -f일반적인 강제 푸시 와 같은 짧은 옵션을 추가 할 때까지 이것을 사용하지 않습니다 :)
ThiefMaster

ha yeah, 자동화 된 스크립트에서 사용했습니다

2

git push -f origin myNewFeature리베이스 된 변경을 추진할 때 이미 사용 된 일반적인 대답 은 좋은 출발점입니다. 이 답변을 작성하여 워크 플로우 중단 여부에 대한 편집을 해결합니다.

우리는 당신이 사용하고있을 거라고 가정하면 git pull --rebase ...(또는 약간의 변형), 원격 지사에 힘 푸시에 의해 휴식이 예에서는 워크 플로가 developer2 병합되는 것을 다음 일은 다음 myNewFeature에를 hisNewFeature. 아무도 그 브랜치에서 작업하지 않는 한 자신의 기능 브랜치를 리베이스 할 수 있으므로 브랜치 영역을 구분하는 규칙이 필요합니다.

이 문제를 해결하려면 mastera) 병합 한 규칙을 설정 하거나 b) develop자신의 myNewFeature분기 를 기반으로하는 통합 분기를 만들고 통합 한 규칙 만 설정하면됩니다 develop. master그러면 마일스톤 또는 릴리스 (또는 다른 설정)를 위해 예약되며 develop각 기능이 다른 기능 분기에 통합 될 준비가되면 각 기능을 푸시하는 위치가됩니다.

이것이 Gitflow 워크 플로의 단순화 된 버전으로 간주 될 수 있다고 생각합니다.


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