Development Tip

기능 브랜치 리베이스 후 Git 푸시가 거부 됨

yourdevel 2020. 9. 28. 10:22
반응형

기능 브랜치 리베이스 후 Git 푸시가 거부 됨


좋아, 나는 이것이 간단한 자식 시나리오라고 생각했는데, 내가 뭘 놓치고 있니?

나는 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완전 해야 함을 의미 합니까 ?

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


문제는 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빨리 감기 병합 만 수행하므로 오류가 발생합니다.

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

제 생각에는 기능 분기를 리베이스 master하고 원격 저장소로 강제 푸시하는 것은 해당 분기에서 작업하는 유일한 사람인 한 괜찮습니다.


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

--force-with-lease

왜? 원격 분기에서 변경 사항을 확인하기 때문에 절대적으로 좋은 생각입니다. James와 Lisa가 동일한 기능 브랜치에서 작업하고 있으며 Lisa가 커밋을 푸시했다고 가정 해 보겠습니다. James는 이제 로컬 브랜치를 리베이스하고 푸시를 시도 할 때 거부됩니다. 물론 James는 이것이 rebase 및 --force 사용 때문이라고 생각하며 Lisa의 모든 변경 사항을 다시 작성합니다. James가 --force-with-lease를 사용했다면 그는 다른 사람이 수행 한 커밋이 있다는 경고를 받았을 것입니다. 리베이스를 추진할 때 --force-with-lease 대신 --force를 사용하는 이유를 알 수 없습니다.


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

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

삭제하면 다른 SHA ID를 포함하는 기존 분기를 푸시하지 못합니다. 이 경우 원격 지점 만 삭제합니다.


이에 대한 한 가지 해결책은 msysGit의 리베이스 병합 스크립트가 수행하는 작업을 수행하는 것입니다. 리베이스 후에 featurewith 의 이전 헤드에 병합합니다 -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

(테스트되지는 않았지만 맞다고 생각합니다 ...)


이 브랜치에 개발자가 한 명 뿐인 경우 일 수도 있고 아닐 수도 있습니다. 즉, 현재 (리베이스 이후) 오리진 / 기능과 인라인되지 않습니다.

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

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

그래, 새 브랜치, 이것은 일반적으로 git의 주요 단점이라고 생각하는 --force없이이 문제를 해결해야합니다.


다른 사람이 귀하의 질문에 답변했습니다. 브랜치를 리베이스하는 경우 해당 브랜치를 강제로 푸시해야합니다.

Rebase and a shared repository generally do not get along. This is rewriting history. If others are using that branch or have branched from that branch then rebase will be quite unpleasant.

In general, rebase works well for local branch management. Remote branch management works best with explicit merges (--no-ff).

We also avoid merging master into a feature branch. Instead we rebase to master but with a new branch name (e.g adding a version suffix). This avoids the problem of rebasing in the shared repository.


My way of avoiding the force push is to create a new branch and continuing work on that new branch and after some stability, remove the old branch that was rebased:

  • Rebasing the checked out branch locally
  • Branching from the rebased branch to a new branch
  • Pushing that branch as a new branch to remote. and deleting the old branch on remote

What is wrong with a git merge master on the feature branch? This will preserve the work you had, while keeping it separate from the mainline branch.

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

Edit: Ah sorry did not read your problem statement. You will need force as you performed a rebase. All commands that modify the history will need the --force argument. This is a failsafe to prevent you from losing work (the old D and E would be lost).

So you performed a git rebase which made the tree look like (although partially hidden as D and E are no longer in a named branch):

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

So, when trying to push your new feature branch (with D' and E' in it), you would lose D and E.


The following works for me:

git push -f origin branch_name

and it does not remove any of my code.

But, if you want to avoid this then you can do the following:

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

then you can cherry-pick all your commits to the new branch. git cherry-pick COMMIT ID and then push your new branch.


For me following easy steps works:

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

After doing all above, we can delete myFeature branch as well by following command:

git push origin --delete myFeature

As the OP does understand the problem, just looks for a nicer solution...

How about this as a practice ?

  • Have on actual feature-develop branch (where you never rebase and force-push, so your fellow feature developers don't hate you). Here, regularly grab those changes from main with a merge. Messier history, yes, but life is easy and no one get's interupted in his work.

  • Have a second feature-develop branch, where one feature team member regulary pushes all feature commits to, indeed rebased, indeed forced. So almost cleanly based on a fairly recent master commit. Upon feature complete, push that branch on top of master.

There might be a pattern name for this method already.

참고URL : https://stackoverflow.com/questions/8939977/git-push-rejected-after-feature-branch-rebase

반응형