Git не відхилено вперед


88

Я відчуваю, що це запитання задавали багато разів, але рішення зазвичай полягає в тому, що "я видалив каталог і знову зробив свою роботу за новим замовленням". Я зробив коміт і натиснув, але зрозумів, що в повідомленні коміту я вказав неправильний номер квитка. Тож я подивився на SO для швидкого рішення і в підсумку набрав у термінал наступне:

$ git reset --soft HEAD^
$ git commit -m "... correct message ..."

Єдина проблема - я отримую таке повідомлення про помилку:

To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

Я використовую модель git-flow і працюю над розробкою. Як я можу об’єднати речі назад, щоб знову зробити git щасливим?


Відповіді:


52

Сила git push:

git push origin +develop

24
Це рішення, але прочитайте коментар Брайана Кемпбелла, щоб ви зрозуміли, що робите, перш ніж використовувати це.
thelem

5
git push origin + master
Aniket Thakur

Див. Також примітку про receive.denyNonFastForwardsу відповіді Брайана Кемпбелла : +або --forceможе бути недостатньо сильним, залежно від того, як вони - ким би вони не були - налаштували своє сховище Git.
торек

174

Якщо натиснути коміт на сервері, а потім переписати цей коміт локально (за допомогою git reset , git rebase, git filter-branchабо будь-яку іншу історію маніпуляції), а потім штовхнули , що переписані фіксації назад на сервер, ви загвинчувати нікого , хто тягнув. Ось приклад; скажімо, що ви вчинили A, і перенесли його на сервер.

- * - * - A <- майстер

- * - * - A <- походження / головний

Тепер ви вирішили переписати A способом, про який ви згадали, скинувши та повторно зафіксувавши. Зверніть увагу, що це залишає звисаючий коміт A, який з часом буде зібраним сміттям, оскільки він недоступний.

- * - * - A
    \
     A '<- майстер

- * - * - A <- походження / головний

Якщо хтось інший, припустимо, Фред, тягне вниз master з сервера, поки ви це робите, у них буде посилання на A, з якого вони можуть почати працювати:

- * - * - A '<- майстер

- * - * - A <- походження / головний

- * - * - AB <- fred / master

Тепер, якби ви змогли просунути ваш A 'до джерела / майстра, який створив би нешвидкий перемотування вперед, він би не мав A в своїй історії. Отже, якщо Фред спробує знову витягнути, йому раптом доведеться об’єднатись і повторно ввести коміт A:

- * - * - A '<- майстер

- * - * - A <- походження / головний

- * - * - AB- \ 
    \ * <- fred / master
     A '- /

Якщо Фред випадково це помітить, то він міг би зробити перебазу, яка запобігла б повторному появі коміту А. Але йому довелося б це помітити і пам’ятати це робити; і якщо у вас є більше, ніж одна людина, яка витягла A, їм усім довелося б перебазувати, щоб уникнути отримання зайвого A коміту в дереві.

Тож, як правило, не є гарною ідеєю змінювати історію на репо, з якого тягнуть інші люди. Якщо ви, однак, знаєте, що ніхто більше не тягне з цього репо (наприклад, це ваше власне приватне репо, або у вас є лише інший розробник, який працює над проектом, з яким ви можете легко координувати), тоді ви можете примусово оновити, запустивши:

git push -f

або

git push origin +master

Вони обидва ігноруватимуть перевірку на швидке просування вперед і оновлять те, що знаходиться на сервері, до вашої нової версії A ', відмовляючись від ревізії A, щоб врешті-решт збирати сміття.

Можливо, що примусові натискання повністю вимкнені за допомогою receive.denyNonFastForwardsопції config. Цей параметр увімкнено за замовчуванням у спільних сховищах. У цьому випадку, якщо ви дійсно, дійсно хочете змусити натиснути, найкращий варіант - видалити гілку та заново створити її за допомогою git push origin :master; git push origin master:master. Однак denyNonFastForwardsопція включена з причини, яка описана вище; на спільному сховищі це означає, що тепер кожному, хто ним користується, потрібно переконатись, що вони перебазуються на новій історії.

У спільному сховищі, як правило, краще просто натискати нові коміти зверху, які виправляють будь-яку проблему; Ви можете використовувати git revertдля створення комітів, які скасовують зміни попередніх комітів.


чудова освіта, і ти зрештою отримав команду, але мою гілку називали розробкою (заснованою на git-flow), а інший хлопець поставив +developсвою команду - так перевірка надходить до нього. У вас і так є астрономічна кількість балів: P
rynmrtn

7
Або скористайтеся менш загадковоюgit push --force
Беннетт МакЕлві

3
@Panique Ви намагаєтеся дозволити кільком людям одночасно працювати над великою, складною базою кодів, не блокуючи один одного (дозволяючи одночасно працювати над нею лише одній людині) і без змін, що перезаписують один одного. Вам потрібно, щоб кожна людина могла самостійно вносити зміни та об’єднувати ці зміни. Злиття (ручне чи автоматичне) може спричинити несподівані проблеми; тому ви хочете зберегти якомога більше інформації, щоб мати змогу з’ясувати, що сталося, якщо вона пішла не так. Це суттєво складно; це не брудно, просто важка проблема.
Брайан Кемпбелл,

Я спробував як -f, так і +, щоб переписати віддалену історію репо. В обох варіантах я зіткнувся з проблемою, що не перемотується вперед. [17:05] $ git push -f origin local_A: remote_A Підрахунок об’єктів: 35, виконано. Дельта стиснення з використанням до 2 потоків. Стискання об’єктів: 100% (18/18), виконано. Написання об'єктів: 100% (21/21), 7,41 КіБ, виконано. Всього 21 (дельта 9), повторно використане 0 (дельта 0) віддалене: щоб запобігти втраті історії, нешвидкі оновлення відхилено. Об'єднайте віддалені зміни (наприклад, "git pull") перед повторним натисканням. Детальніше див. У розділі "Примітка про швидке перемотування вперед" розділу "git push --help".
Шрікант

4
@Srikanth Можна повністю вимкнути примусові натискання за допомогою receive.denyNonFastForwardsопції конфігурації. Цей параметр увімкнено за замовчуванням у спільних сховищах. У цьому випадку, якщо ви дійсно, дуже хочете змусити натиснути, найкращим варіантом є видалення гілки та повторне її створення за допомогою git push origin :remote_A; git push origin local_A:remote_A. Але прочитайте те, що я писав вище про те, чому це погана ідея робити подібний робочий процес у спільному сховищі. Спробуйте зробити це лише у тому випадку, якщо у вас є щось, що викликає серйозні проблеми у фіксації, від якої ви намагаєтеся позбутися або переписати.
Брайан Кемпбелл

14

Можливо, вам доведеться зробити git pull, що МОЖЕ автоматично об’єднати речі для вас. Тоді ви можете зробити ще раз. Якщо у вас виникли конфлікти, вам буде запропоновано їх вирішити.

Майте на увазі, вам слід вказати, з якої гілки витягувати, якщо ви не оновили gitconfig, щоб вказати ...

Наприклад:

git pull origin develop:develop

Досі божевільний щодо нешвидкого перемотування вперед. Будь-які думки про те, як змусити його злитися? ! [rejected] develop -> develop (non-fast-forward)
rynmrtn

Я думаю, що перемикач -f, але я можу помилитися. kernel.org/pub/software/scm/git/docs/git-pull.html
Тоні

Це частково працює. Однак я не бачу оновлень на github (він показує попередній git push origin develop
коміт

7

Я використовував EGit, і я також стикався з цією проблемою. Просто спробував до rebaseпоточної гілки і це спрацювало.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.