Коротка відповідь
Ви пропустили той факт, що ви бігли 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 заснований на ряді факторів, одним з яких є хеш коміту, який виходить перед ним.
Якщо ви будете упорядковувати комісії, ви зміните хеші фіксування; rebasing (коли він щось робить) змінить хеші фіксації. При цьому результат запущеного тексту 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
:
Подивіться на reflog ( git 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 включно) на цю нову гілку, і трактуйте цю нову гілку як канонічну.
- Виконати
git rebase --interactive $commit
, де $commit
є фіксація перед обома дублюючими командами 2 . Тут ми можемо прямо видалити рядки для дублікатів.
1 Не має значення, яку з двох ви обираєте, ba7688a
або 2a2e220
працюєте чудово.
2 У прикладі це було б 85f59ab
.
TL; DR
Набір advice.pushNonFastForward
для false
:
git config --global advice.pushNonFastForward false