짧은 답변
를 실행했다는 사실을 생략하고 git push
다음 오류가 발생한 다음 계속 실행했습니다 git pull
.
To git@bitbucket.org:username/test1.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Git이 도움이 되려고하지만 'git pull'충고는 당신이하고 싶은 일이 아닐 가능성이 큽니다. .
당신이있는 경우:
- "기능 브랜치"또는 "개발자 브랜치" 단독 으로 작업 한 다음 실행
git push --force
하여 리베이스 이후 커밋으로 원격 업데이트를 실행할 수 있습니다 ( user4405677의 답변에 따라 ).
- 동시에 여러 개발자와 브랜치에서 작업하는 경우 처음에는 사용하지 않아야 할 것입니다
git rebase
. 의 dev
변경 사항으로 업데이트하려면을 실행 하는 master
대신 git rebase master dev
실행 git merge master
하는 동안 실행해야합니다 dev
( Justin의 답변에 따라 ).
약간 더 긴 설명
Git의 각 커밋 해시는 여러 요소를 기반으로하며, 그중 하나는 그 전에 오는 커밋의 해시입니다.
커밋을 재정렬하면 커밋 해시가 변경됩니다. 리베이스 (무언가를 할 때)는 커밋 해시를 변경합니다. 그것으로, 실행의 결과 git rebase master dev
, dev
와 동기화되어 master
, 만듭니다 새 에 그와 같은 내용 (따라서 및 해시) 커밋 dev
만에 커밋과 master
그들 앞에 삽입합니다.
여러 가지 방법으로 이와 같은 상황에 처할 수 있습니다. 내가 생각할 수있는 두 가지 방법 :
- 당신은 당신의
master
기반을 원하는 커밋을 가질 수 있습니다dev
작업의 .
dev
이미 원격으로 푸시 된 커밋이있을 수 있으며 , 변경을 진행할 수 있습니다 (커밋 메시지 재정렬, 커밋 재정렬, 스쿼시 커밋 등).
무슨 일이 일어 났는지 더 잘 이해하겠습니다. 여기에 예가 있습니다.
저장소가 있습니다.
2a2e220 (HEAD, master) C5
ab1bda4 C4
3cb46a9 C3
85f59ab C2
4516164 C1
0e783a3 C0
그런 다음 커밋 변경을 진행합니다.
git rebase --interactive HEAD~3 # Three commits before where HEAD is pointing
(여기에서 내 말을 받아 들여야합니다. Git에서 커밋을 변경하는 방법에는 여러 가지가 있습니다.이 예제에서는의 시간을 변경 C3
했지만 새 커밋을 삽입하고 커밋 메시지를 변경하고 커밋을 재정렬하고, 함께 커밋 스쿼시 등)
ba7688a (HEAD, master) C5
44085d5 C4
961390d C3
85f59ab C2
4516164 C1
0e783a3 C0
이것은 커밋 해시가 다르다는 것을 알아 차리는 것이 중요합니다. 이것은 당신이 그들에 대해 (무엇이든) 변경했기 때문에 예상되는 동작입니다. 괜찮지 만 :
푸시를 시도하면 오류가 표시되고 실행해야한다는 힌트가 표시됩니다 git pull
.
$ git push origin master
To git@bitbucket.org:username/test1.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
를 실행하면 git pull
다음 로그가 표시됩니다.
7df65f2 (HEAD, master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 (origin/master) C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
또는 다른 방법으로 표시 :
이제 로컬에 중복 커밋이 있습니다. 우리가 실행한다면 우리는 git push
그것들을 서버로 보낼 것입니다.
이 단계에 도달하는 것을 피하기 위해 우리는 git push --force
(대신에 우리 가 달리는 곳) 달릴 수 있습니다 git pull
. 이것은 새로운 해시가있는 커밋을 문제없이 서버로 보냈을 것입니다. 이 단계에서 문제를 해결하기 위해 실행하기 전으로 재설정 할 수 있습니다 git pull
.
우리가 실행 하기 전에git reflog
커밋 해시가 무엇인지 보려면 reflog ( )를보십시오 .git pull
070e71d HEAD@{1}: pull: Merge made by the 'recursive' strategy.
ba7688a HEAD@{2}: rebase -i (finish): returning to refs/heads/master
ba7688a HEAD@{3}: rebase -i (pick): C5
44085d5 HEAD@{4}: rebase -i (pick): C4
961390d HEAD@{5}: commit (amend): C3
3cb46a9 HEAD@{6}: cherry-pick: fast-forward
85f59ab HEAD@{7}: rebase -i (start): checkout HEAD~~~
2a2e220 HEAD@{8}: rebase -i (finish): returning to refs/heads/master
2a2e220 HEAD@{9}: rebase -i (start): checkout refs/remotes/origin/master
2a2e220 HEAD@{10}: commit: C5
ab1bda4 HEAD@{11}: commit: C4
3cb46a9 HEAD@{12}: commit: C3
85f59ab HEAD@{13}: commit: C2
4516164 HEAD@{14}: commit: C1
0e783a3 HEAD@{15}: commit (initial): C0
위에서 우리가 ba7688a
실행하기 전의 커밋 임을 알 수 git pull
있습니다. 해당 커밋 해시를 사용하여 해당 ( git reset --hard ba7688a
)로 재설정 한 다음 실행할 수 있습니다.git push --force
있습니다.
그리고 우리는 끝났습니다.
하지만 잠깐, 중복 된 커밋을 기반으로 계속 작업했습니다.
어떻게 든 커밋이 중복 된 것을 알아 차리지 못하고 중복 커밋 위에서 계속 작업을 진행했다면 정말 엉망이 된 것입니다. 엉망의 크기는 중복 위에있는 커밋 수에 비례합니다.
이것이 어떻게 생겼는지 :
3b959b4 (HEAD, master) C10
8f84379 C9
0110e93 C8
6c4a525 C7
630e7b4 C6
070e71d (origin/master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
또는 다른 방법으로 표시 :
이 시나리오에서는 중복 커밋을 제거하고이를 기반으로 한 커밋을 유지하려고합니다. C6에서 C10까지 유지하려고합니다. 대부분의 경우와 마찬가지로 다음과 같은 여러 가지 방법이 있습니다.
어느 한 쪽:
- 커밋 중복 마지막에 새로운 지점을 만듭니다 1 ,
cherry-pick
각각 그 새로운 지점에 (C6 C10의 포함을 통해) 커밋과 정식으로 치료하는 새로운 지점.
- Run
git rebase --interactive $commit
, 여기서는 복제 된 커밋 2 이전$commit
의 커밋 입니다. 여기에서 중복 된 줄을 완전히 삭제할 수 있습니다.
1 그것은 하나, 당신은 선택이 어떤 중요하지 않습니다 ba7688a
또는 2a2e220
잘 작동.
2 예에서는 85f59ab
.
TL; DR
설정 advice.pushNonFastForward
합니다 false
:
git config --global advice.pushNonFastForward false