Як я можу натиснути виправлену фіксацію на віддалений репозиторій Git?

Коли я трохи попрацював з вихідним кодом, я зробив свою звичайну річ, а потім я натиснув на віддалений репозиторій. Але потім я помітив, що забув організувати імпорт в вихідний код. Тому я роблю команду зміни, щоб замінити попередню фіксацію:

 > git commit --amend 

На жаль, фіксація не може бути повернута в репозиторій. Він відхиляється наступним чином:

 > git push origin To //my.remote.repo.com/stuff.git/ ! [rejected] master -> master (non-fast forward) error: failed to push some refs to '//my.remote.repo.com/stuff.git/' 

Що мені робити? (Я можу отримати доступ до віддаленого сховища.)

475
31 окт. заданий Spoike 31 Жовтня. 2008-10-31 13:23 '08 о 13:23 2008-10-31 13:23
@ 13 відповідей

Я насправді одного разу натиснув репозиторій --force і .git і отримав лайка від Linus BIG TIME. Загалом, це створить масу проблем для інших людей. Проста відповідь: "Не роби цього".

Я бачу, що інші давали рецепт для цього, так що я не буду повторювати їх тут. Але ось підказка, щоб оговтатися від ситуації після того, як ви виштовхнули виправлену фіксацію за допомогою --force (або + master).

  • Знайдіть старий Комміт, який ви внесли в нього (назвіть його old , і ми виберемо новий команд, який ви створили, змінивши new ).
  • Створіть злиття між old і new , записавши дерево new , наприклад git checkout new git merge -s ours old .
  • Об'єднайте це з вашим майстром за допомогою git merge master
  • Оновлення свій майстер за допомогою результату git push . HEAD:master git push . HEAD:master
  • Вивести результат.

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

371
11 янв. відповідь дан gitster 11 Січня. 2009-01-11 10:36 '09 о 10:36 2009-01-11 10:36

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

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

Якщо ви знаєте, що ви єдина людина, що натиснув, і ви хочете натиснути виправлену фіксацію або натиснути фіксацію, яка вітру гілка, ви можете "примусово" Git оновити віддалену гілку за допомогою -f перемикач.

 git push -f origin master 

Навіть це може не працювати, оскільки Git дозволяє віддаленим репозиторіїв відмовлятися від швидких натиснень в дальньому кінці за допомогою змінної конфігурації receive.denynonfastforwards . Якщо це так, причина відхилення буде виглядати так (зверніть увагу на частину "віддалений відмова"):

border=0
  ! [remote rejected] master -> master (non-fast forward) 

Щоб обійти це, вам потрібно або змінити конфігурацію віддаленого сховища, або як брудний зламати, ви можете видалити і відтворити гілку таким чином:

 git push origin :master git push origin master 

У загальному випадку останній параметр git push використовує формат <local_ref>:<remote_ref> , де local_ref - це ім'я гілки в локальному репозиторії, а remote_ref - ім'я гілки в віддаленому репозиторії. Ця пара команд використовує два скорочення. :master має значення null local_ref, що означає встановлення нульової гілки віддаленій стороні master , тобто видалення віддаленої гілки. Ім'я гілки без : означає, що локальна гілка з вказаним ім'ям перенаправляється в віддалену гілку з тим же ім'ям. master в цій ситуації є коротким для master:master .

218
01 нояб. відповідь дан Charles Bailey 01 нояб. 2008-11-01 00:58 '08 в 0:58 2008-11-01 00:58

Швидкий просторікування: той факт, що ніхто не опублікував проста відповідь, демонструє відчайдушну ворожість користувача, виявлену за допомогою Git CLI.

У будь-якому випадку, "очевидний" спосіб зробити це, припускаючи, що ви не намагалися змусити поштовх, - це витягнути першим. Це призведе до зміни, яке ви внесли в нього (і, отже, його більше немає), щоб він знову з'явився.

Як тільки ви дозволите будь-які конфлікти, ви можете натиснути ще раз.

Отже:

 git pull 

Якщо ви отримуєте помилки в pull, можливо, щось не так у вашій конфігурації локального сховища (у мене був невірний ref в розділі .git / config).

І після

 git push 

Можливо, ви отримаєте додаткову фіксацію з предметом, розповідають про "Trivial merge".

184
22 сент. відповідь дан Tim Band 22 сент. 2009-09-22 13:46 '09 о 13:46 2009-09-22 13:46

Коротка відповідь: не натискайте виправлені фіксації на публічне репо.

Довгий відповідь: кілька команд Git, таких як git commit --amend і git rebase , фактично переписують графік історії. Це прекрасно, поки ви не опублікували свої зміни, але як тільки ви це зробите, ви дійсно не повинні обманювати історію, тому що, якщо хто-то вже отримав ваші зміни, тоді, коли вони спробують знову витягнути, Замість того, щоб вносити зміни в комерц, ви повинні просто зробити нову фіксацію зі змінами.

Однак, якщо ви дійсно хочете натиснути виправлене повідомлення, ви можете зробити це в такий спосіб:

 $ git push origin +master:master 

Ведучий знак + змусить натиснути, навіть якщо це не призведе до фіксації "швидкого перемотування вперед". (Швидка переадресація відбувається, коли зміни, які ви натискаєте, є прямим нащадком змін, які вже перебувають в публічному репо.)

86
31 окт. відповідь дан mipadi 31 Жовтня. 2008-10-31 17:35 '08 о 17:35 2008-10-31 17:35

Ось простий і чистий спосіб зробити ваші зміни після того, як ви вже зробили commit --amend :

 git reset --soft HEAD^ git stash git push -f origin master git stash pop git commit -a git push origin master 

Що робить наступне:

  • Reset відгалуження гілки головки на батьківський.
  • Натисніть останнім Ком.
  • Примусове натискання на пульті дистанційного керування. Тепер віддалений комп'ютер не має останнього фіксації.
  • Потрапити в свій гаманець.
  • Читай чисто.
  • Натисніть на пульті дистанційного керування.

Не забудьте змінити "origin" і "master", якщо застосувати це до іншій гілці або віддаленого пристрою.

20
21 июня '15 в 17:41 2015-06-21 17:41 відповідь дан Faiza 21 червня '15 о 17:41 2015-06-21 17:41

Я вирішив це, відкинувши локальне виправлення і додавши нові зміни зверху:

 # Rewind to commit before conflicting git reset --soft HEAD~1 # Pull the remote version git pull # Add the new commit on top git add ... git commit git push 
16
24 сент. відповідь дан bara 24 вересня. 2012-09-24 18:46 '12 о 18:46 2012-09-24 18:46

У мене була та ж проблема.

  • Випадково скоригована остання фіксація, яка вже була натиснута
  • Зроблено багато змін локально, скоєно в п'ять разів
  • Намагався натиснути, отримати помилку, запанікувати, об'єднати віддалений доступ, отримати багато не-моїх файлів, натиснув, не вдалося і т.д.

Як Git -newbie, я думав, що він завершений FUBAR .

Рішення. Дещо по-іншому, як @bara запропонувала + створити локальну гілка резервного копіювання

 # Rewind to commit just before the pushed-and-amended one. # Replace <hash> with the needed hash. # --soft means: leave all the changes there, so nothing is lost. git reset --soft <hash> # Create new branch, just for a backup, still having all changes in it. # The branch was feature/1234, new one - feature/1234-gone-bad git checkout -b feature/1234-gone-bad # Commit all the changes (all the mess) not to lose it  not to carry around git commit -a -m "feature/1234 backup" # Switch back to the original branch git checkout feature/1234 # Pull the from remote (named 'origin'), thus 'repairing' our main problem git pull origin/feature/1234 # Now you have a clean-and-non-diverged branch and a backup of the local changes. # Check the needed files from the backup branch git checkout feature/1234-gone-bad -- the/path/to/file.php changes # Rewind to commit just before the pushed-and-amended one. # Replace <hash> with the needed hash. # --soft means: leave all the changes there, so nothing is lost. git reset --soft <hash> # Create new branch, just for a backup, still having all changes in it. # The branch was feature/1234, new one - feature/1234-gone-bad git checkout -b feature/1234-gone-bad # Commit all the changes (all the mess) not to lose it  not to carry around git commit -a -m "feature/1234 backup" # Switch back to the original branch git checkout feature/1234 # Pull the from remote (named 'origin'), thus 'repairing' our main problem git pull origin/feature/1234 # Now you have a clean-and-non-diverged branch and a backup of the local changes. # Check the needed files from the backup branch git checkout feature/1234-gone-bad -- the/path/to/file.php 

Можливо, це не швидка і чисте рішення, і я втратив свою історію (1 commit замість 5), але він зберіг денну роботу.

7
20 февр. відповідь дан davisca 20 февр. 2014-02-20 13:24 '14 о 13:24 2014-02-20 13:24

Якщо ви знаєте, що ніхто не потягнув ваше виправлення без змін, використовуйте параметр --force-with-lease git push .

У TortoiseGit ви можете зробити те ж саме в настройках "Push ..." "Force: May discard" і перевірка "відомих змін".

Force (може відхилити відомі зміни) дозволяє віддаленому сховища приймати більш безпечний, не швидкий перехід. Це може привести до того, що віддалений репозиторій втратить фіксації; використовуйте його з обережністю. Це може перешкодити втратити невідомі зміни від інших людей на пульті дистанційного керування. Він перевіряє, вказує чи гілка сервера на ту ж фіксацію, що і гілка віддаленого відстеження (відомі зміни). Якщо так, то буде натиснута сила. В іншому випадку він буде відхилений. Оскільки git не має тегів з віддаленим відстеженням, теги не можуть бути перезаписані за допомогою цієї опції.

3
07 июня '16 в 3:03 2016-06-07 03:03 відповідь дан ShawnFeatherly 07 червня '16 в 3:03 2016-06-07 3:03

Ось простий і чистий спосіб внести зміни після того, як ви вже зробили git add "your files" і git commit --amend :

 git push origin master -f 

або

 git push origin master --force 
2
18 янв. відповідь дан Marwen Bkh 18 Січня. 2016-01-18 11:29 '16 о 11:29 2016-01-18 11:29

Якщо ви не натиснули код на віддалену гілку (GitHub / Bitbucket), ви можете змінити повідомлення фіксації в командному рядку, як показано нижче.

  git commit --amend -m "Your new message" 

Якщо ви працюєте над певною гілкою, зробіть наступне:

 git commit --amend -m "BRANCH-NAME: new message" 

Якщо ви вже натиснули на код з неправильним повідомленням, вам потрібно бути обережним при зміні повідомлення. після того як ви зміните повідомлення фіксації і спробуйте знову натиснути його, у вас виникнуть проблеми. Щоб зробити його гладким, виконайте наступні кроки.

Будь ласка, прочитайте весь відповідь, перш ніж робити це

 git commit --amend -m "BRANCH-NAME : your new message" git push -f origin BRANCH-NAME # Not a best practice. Read below why? 

Важливе зауваження:. Коли ви використовуєте примусове натискання, ви можете зіткнутися з проблемами коду, які інші розробники працюють над однією гілкою. Тому, щоб уникнути цих конфліктів, вам потрібно витягнути код зі своєї гілки, перш ніж натискати force:

  git commit --amend -m "BRANCH-NAME : your new message" git pull origin BRANCH-NAME git push -f origin BRANCH-NAME 

Це найкраща практика при зміні повідомлення фіксації, якщо воно вже було натиснуто.

2
13 янв. відповідь дан Packer 13 Січня. 2015-01-13 10:20 '15 о 10:20 2015-01-13 10:20

Ви отримуєте цю помилку, тому що у Git remote вже є ці файли фіксації. Ви повинні примусово натиснути на гілку, щоб це працювало:

 git push -f origin branch_name 

Також переконайтеся, що ви витягуєте код з віддаленого, так як хтось із вашої команди міг переміститися в одну гілку.

 git pull origin branch_name 

Це один з випадків, коли нам потрібно примусово натиснути фіксацію на віддалений.

1
21 янв. відповідь дан Praveen Dhawan 21 Січня. 2016-01-21 09:35 '16 о 9:35 2016-01-21 9:35

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

1
31 окт. відповідь дан Spoike 31 Жовтня. 2008-10-31 14:39 '08 о 14:39 2008-10-31 14:39

Я просто продовжував робити те, що сказав мені Git. Отже:

  • Неможливо натиснути через виправлення.
  • Я роблю спробу, як передбачалося.
  • Помилка злиття. тому я виправляю його вручну.
  • Створіть нову фіксацію (позначену "merge") і натисніть його.
  • Здається, що це працює!

Примітка. Змінена фіксація була останньою.

1
02 дек. відповідь дан Rolf 02 дек. 2016-12-02 19:29 '16 о 19:29 2016-12-02 19:29

Інші питання по мітках або Задайте питання