git stash blunder: git stash pop та закінчилося конфліктами злиття


200

Я зробив git stash popі закінчився конфліктами злиття. Я вилучив файли з файлової системи і зробив так, git checkoutяк показано нижче, але він вважає, що файли все ще вимкнено. Потім я спробував замінити файли і git checkoutповторив той самий результат. Я подія намагалася примусити його -fпрапором. Будь-яка допомога буде вдячна!

chirag-patels-macbook-pro:haloror patelc75$ git status
app/views/layouts/_choose_patient.html.erb: needs merge
app/views/layouts/_links.html.erb: needs merge
# On branch prod-temp
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   db/schema.rb
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       unmerged:   app/views/layouts/_choose_patient.html.erb
#       unmerged:   app/views/layouts/_links.html.erb

chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb
error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb
warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged

Примітка: відновлення стану до цього git stash apply/popповинно бути простіше за допомогою Git 2.5 (Q2 2015), оскільки робоче дерево тепер має бути чистим: дивіться мою відповідь нижче
VonC

Відповіді:


219

Дивіться man git merge ( ЯК РЕШИТИ КОНФЛІКТИ ):

Побачивши конфлікт, ви можете зробити дві речі:

  • Вирішіть не зливатися. Єдині необхідні очищення - це скинути індексний файл до зобов’язання HEAD, щоб повернути реверс 2. та очистити зміни робочого дерева, внесені на 2. і 3.; git-reset - для цього можна використовувати твердий.

  • Вирішіть конфлікти. Git позначить конфлікти в робочому дереві. Відредагуйте файли у формі та git додайте їх до індексу. Використовуйте git commit для укладення угоди.

І в розділі ІСТИНА МЕРГ (щоб побачити, на що йдеться 2. і 3.):

Коли не очевидно, як узгодити зміни, відбувається таке:

  1. Вказівник HEAD залишається таким же.

  2. Посилання MERGE_HEAD встановлюється так, щоб вказати на іншу головну гілку.

  3. Шляхи, об'єднані чисто, оновлюються як у файлі індексу, так і у вашому робочому дереві.

  4. ...

Отже: використовуйте, git reset --hardякщо ви хочете видалити зміни зі сховища зі свого робочого дерева, або git resetякщо ви хочете просто очистити індекс і залишити конфлікти у вашому робочому дереві для злиття вручну.

Під скринькою man git ( OPTIONS, pop ) ви можете прочитати додатково:

Застосування держави може провалитися при конфліктах; у цьому випадку він не видаляється зі списку сховищ. Необхідно вирішити конфлікти вручну і вручну зателефонувати на зберігання git stash


9
Насправді, навіть після того, як ви скинете скриньку, все одно можна (хоч і складніше) отримати її ще раз, оскільки набір змін все ще існує в сховищі. stackoverflow.com/search?q=git+recover+dropped+stash
Филс

3
@nalply: це добре чи погано? Ви можете вдосконалити мою відповідь, де ви її в першу чергу не зрозуміли ...
tanascius

1
Я думаю, що перегляд вихідного коду є складною проблемою. Легко заплутатися. Я все ще думаю, що ваша відповідь хороша, тому що вона підтвердила мій підхід.
nalply

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

11
"Застосування стану може не вдатися до конфліктів; у цьому випадку він не видаляється зі списку скриньок." На мою думку, це найважливіша частина поста. Спробуйте відредагувати свою відповідь, щоб викласти її напроти, а також слова НЕ ПАНІКА великими, доброзичливими літерами. (+1 хоч уже.) Дякую.
Патрік М

42

У мене було подібне, що трапилося зі мною. Я ще не хотів виставляти файли ще, тому я додав їх, git addа потім просто зробив git reset. Це в основному лише додало, а потім змінило зміни моїх змін, але очистило нерозбірливі шляхи.


4
Це здається кращим, ніж використання, reset --hardоскільки воно не перезаписує ваші файли (крім тих, що мають проблеми зі злиттям). Дякую!
sinelaw

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

2
git addставить їх, але те git reset, що я роблю одразу після, знеструмлює їх. По суті, він очищає нерозкладені шляхи і повертає мене до мого нормального робочого дерева, підробляючи git out.
Аарон

3
Вам не потрібно, git addякщо ви збираєтесь git reset. В git resetефективно «Скасовує» в git add. git reset( --mixed<- за замовчуванням) фактично не торкається робочого каталогу, тому саме те, що було у вашому робочому каталозі, конфлікти злиття та все, залишаються в спокої. Індекс (а технічно заголовок гілки) скидається, хоча (без посилання вони повертаються назад HEAD, що, ймовірно, означає відсутність змін для голови гілки, і фактично скасовує будь-яке git addзроблене до індексу, а також очищення стану нерозподілених шляхів) .
бамбук

3
Послідовність , редагувати / рішучість , git resetі git stash dropпрацює добре. Це робить те, що git stash popбуло б без конфліктів. Здається, git addце не потрібно; хоча це може бути корисним, у вас є багато файлів із конфліктами. Коли кожне вирішене , їх можна додавати і git statusслідкувати за ними.
невгамовний шум

13

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

Після цього ви можете git resetвнести всі зміни з індексу до робочої директорії, оскільки, мабуть, у разі конфлікту зміни неконфліктних файлів залишаються в індексі.

Ви також можете запустити git stash drop [<stash name>]згодом, щоб позбутися від сховища, тому git stash popщо не видаляє його у випадку конфліктів.


2

Зауважте, що Git 2.5 (ІІ квартал 2015 р.) майбутній Git може спробувати зробити такий сценарій неможливим.

Див. Комісію ed178ef від Джеффа Кінга ( peff), 22 квітня 2015 р.
(Об'єднав Хуніо С Хамано - gitster- у комітеті 05c3967 , 19 травня 2015 р.)

Примітка. Це відновлено. Дивіться нижче .

stash: вимагає чистий індекс, щоб застосувати / поп

Проблема

Якщо ви поставили вміст у своєму індексі та запустіть " stash apply/pop", ми можемо потрапити в конфлікт і поставити нові записи в індекс.
Повернутися до початкового стану на цьому етапі складно, тому що такі інструменти, як "git reset --keep", підірвуть все, що буде зроблено .

Іншими словами:

" git stash pop/apply" забув переконатися, що не тільки робоче дерево чисте, але й індекс чистий.
Останнє важливо, оскільки прихований додаток може конфліктувати, а індекс буде використаний для вирішення конфлікту.

Рішення

Ми можемо зробити це більш безпечним, відмовившись від подання заявок, коли є поетапні зміни.

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

Cannot apply stash: Your index contains uncommitted changes.

Змусити вас здійснити зміни означає, що у випадку злиття ви можете легко відновити початковий стан (раніше git stash apply/pop) за допомогою a git reset --hard.


Див. Команду 1937610 (15 червня 2015 р.) Та виконувати ed178ef (22 квітня 2015 р.) Джеффа Кінга ( peff) .
(Об’єднав Хуніо С Хамано - gitster- у комітеті bfb539b , 24 червня 2015 р.)

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

На жаль, це шкодить деяким загальним робочим потокам навколо " git stash -k", наприклад:

git add -p       ;# (1) stage set of proposed changes
git stash -k     ;# (2) get rid of everything else
make test        ;# (3) make sure proposal is reasonable
git stash apply  ;# (4) restore original working tree

Якщо ви "git commit" між кроками (3) і (4), це просто працює. Однак, якщо ці кроки є частиною гачка попереднього здійснення, у вас немає такої можливості (вам потрібно відновити початковий стан незалежно від того, пройшли тести чи не вдалися).

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