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

우리는 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을 싫어합니까?



답변

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

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'

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


답변

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

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


답변

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

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

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

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

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

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

git push -f origin newfeature

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

git push origin :newfeature
git push origin newfeature

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

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

git reflog

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


답변

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

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


답변

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

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

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

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


답변

나는 MrCholo에 동의하며 , 아마도 Trevor Norris 는 대체하기 위해 좋은 답변 을 업데이트하는 것을 고려할 수 있습니다.

git push -f origin devel0

git push --force-with-lease origin devel0


답변