Як вирішити конфлікт git stash без комісій?


494

Як мені задано в цьому запитанні , я також хочу знати, як вирішити конфлікт, git stash popне додаючи до нього будь-яких модифікацій (так само, як "git stash pop" без конфлікту).

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

git stash pop -> CONFLICT
git stash drop
[resolve conflict]
[add conflict files]
git reset HEAD <all files that are in commit-mode>

[Оновити] Спосіб відтворення:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27: До прикладу додали новий файл під назвою "третій", щоб показати, що обхідні шляхи, як рішення з scy, працюють лише для порожніх HEAD, але не виправляють початкову проблему, що HEAD не має такого ж вмісту, як для git stash popбез конфлікту.


Отже, ви git addвирішили конфліктні файли, фактично розміщуючи їх в індексі, і ви хочете не мати їх у нашому індексі?
Ромен

Так, правильно. Я просто хочу поведінку, яка git stash popвиникає, коли не виникає конфлікту (але з повідомленням, які файли потрібно об'єднати).
Свен

2
Здається, відповідь на це є тут: stackoverflow.com/questions/3945826/git-stash-questions . У обраній відповіді, на 4-му коментарі, Адам пояснює, чому git робить це.
Патрік

@Patrick Дякую за цю інформацію - тому, здається, рішення не буде, оскільки його "за задумом"
Sven

Відповіді:


508

Не слідкуйте за іншими відповідями

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

Чистий розчин

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

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Тож давайте зробимо те, що пропонує Git (не роблячи жодних непотрібних зобов’язань):

  1. Вручну (або використовуючи якийсь інструмент злиття , див. Нижче) вирішити конфлікти.
  2. Використовуйте git resetдля позначення конфлікту (конфліктів) як вирішеного та знеструмлення змін. Ви можете виконати його без будь-яких параметрів, і Git видалить все з індексу. Ви не повинні виконувати git addраніше.
  3. Нарешті, видаліть скриньку git stash drop, оскільки Git не робить цього конфлікту.

Переведено в командний рядок:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

Пояснення поведінки за замовчуванням

Є два способи позначення конфліктів як вирішених: git addта git reset. Хоча git resetпозначає конфлікти як вирішені та видаляє файли з індексу, git addконфлікти також позначає як вирішені, але зберігає файли в індексі.

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

Інструменти злиття

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


32
@kamalpal, здається, це потрібно, коли git stash popне вдається зіткнутися з конфліктами.
Еміль Бержерон

21
@kamalpal так, Git навіть повідомляє вас, що приховування не було скинуто у випадку конфлікту. І питання стосувалося такого випадку, тому вам справді потрібно виконати,git stash drop якщо ви не хочете зберегти цю скриньку.
Девід Ференчі Рогожан

@ DavidFerenczyRogožan Git взагалі не сповістив мене про те, що він не скинув запис на скриньку. Версія 2.17.1 тут.
Роберт Сімер

298

Припустимо, у вас є такий сценарій, коли ви зберігаєте свої зміни, щоб вийти з місця походження. Можливо тому, що ваші локальні зміни є лише debug: trueу файлі налаштувань. Тепер ви потягнете, і хтось там запровадив нове налаштування, створивши конфлікт.

git status каже:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Добре. Я вирішив піти з тим, що запропонував Гіт: Я вирішив конфлікт і покінчив:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Тепер моя робоча копія знаходиться у такому стані, як я хочу, але я створив зобов’язання, якого я не хочу мати. Як я можу позбутися цього зобов'язання, не змінюючи свою робочу копію? Зачекайте, є популярна команда для цього!

git reset HEAD^

Моя робоча копія не змінена, але комісія WIP відсутня. Саме цього я хотів! (Зверніть увагу, що я --softтут не використовую , тому що якщо у вашому сховищі є файли з автоматичним злиттям, вони автоматично стадіюються, і, таким чином, після закінчення цих файлів ви знову будете інсценовані післяreset .)

Але залишається ще одне: сторінка man git stash popнагадує нам, що "Застосування стану може не вдатися до конфліктів; в цьому випадку він не видаляється зі списку скриньки. Вам потрібно вирішити конфлікти вручну та зателефонувати git stash dropвручну". Тож саме це ми і робимо зараз:

git stash drop

І зробили.


34
Просто багато спадкової потворності у свідомому необхідності виконувати скидання HEAD ^ ... для чогось, що повинно впливати лише на працююче дерево.

6
Чому б не просто вирішити конфлікти, а потім git add <resolved conflict files>слідувати git reset HEAD?
BoltzmannBrain

Дякую за пропозицію, але це не вирішує початкову проблему, що це не та сама поведінка, як git stash popбез конфлікту. Просто додайте ще один файл до HEAD перед тим, як робити конфлікт, git stash popі тоді ваш git commit -a -m WIPдодав би новий файл до комісії. Але без конфлікту просто новий файл залишиться в HEAD, але не у git stash popфайлах.
Свен

7
Я не думаю, що потрібно спочатку виконувати, а потім скасовувати. Просто скиньте з відповіді Давіда Ференчі , зробимо те саме
vladkras

3
Для користувачів Windows, ^використання використовується як спеціальне продовження рядків і залишить вас сидіти в Більше? підказка замість виконання команди. Замість того, щоб використовувати: git reset --soft HEAD~1. Подивіться, як виконувати-i-delete-unpushed-git-commits?
mrfelis

87

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

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

Можливо, має існувати режим скидання, який виконує обидва ці речі одночасно, хоча зараз його немає.


2
Режим скидання - це той, який я шукаю - інші способи вирішення подібні до того, який я описав, і не практичний для більш ніж 5 файлів.
Свен

25
А потім використовуйте "git stash drop", щоб закінчити "git stash pop".
Девід Лю

2
Хоча питання не задає це питання явно, може бути корисним оновити відповідь, щоб включити "git stash drop", оскільки сховище не випадає автоматично у випадку конфлікту.
Абхішек Патхак

29
git checkout stash -- .

працював на мене.

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


Це допомогло, коли "git pull --autostash" вводить небажані об'єднання і git checkout приховування -. безумовно переписує конфлікти зі сховища
Алек Істомін

11
git add .
git reset

git add . встановить ВСІ файли, що повідомляють git, що ви вирішили конфлікт

git reset буде нестабільним ВСЕ поетапні файли без створення комітів


Це насправді не є поганою відповіддю, це майже так, як git add -uтодіgit reset
ebob

4

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

git stash apply --index

ось повне пояснення:

http://git-scm.com/book/en/Git-Tools-Stashing


Дякую за цей підказку, але це не допоможе, коли я вже це зробив git stash pop- чи є спосіб повернути це та зробити, git stash apply --indexколи я дізнався, що git stash popвиникне конфлікт?
Свен

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

3
Якщо ви подивитесь на нижню частину цієї публікації ТУТ, вона говорить, що якщо ви запустите, git stash popі це закінчиться конфліктами, приховування не видаляється ... так що ви можете бігти, git reset --hardщоб скасувати поп, а потім спробувати запропоноване нами рішення.
Марко Понті

Просто спробував це, і він не працює після того, як у вас файл у конфліктному стані. Навіть якщо ви вирішите конфлікт вручну.
Sam3k

2

git stash branchбуде робота, яка створює нову гілку для вас, перевіряє виконання вами зобов'язань, коли ви приховували свою роботу, знову додає свою роботу там, а потім скидає приховування, якщо воно успішно застосовується. перевірити це


2

Найшвидший спосіб, який я знайшов, - це вирішити конфлікт, потім зробити git add -u, а потім зробити git reset HEAD, що навіть не передбачає жодних зобов'язань.


1

Відповідно до запитань щодо git stash , після виправлення конфлікту,git add <file> - це правильний хід дій.

Саме після прочитання цього коментаря я зрозумів, що зміни автоматично додаються до індексу (за дизайном). Ось чому git add <file>завершується процес вирішення конфлікту.


-1

Це не найкращий спосіб зробити це, але це працює:

$ git stash apply
$ >> resolve your conflict <<
$ >> do what you want to do with your code <<
$ git checkout HEAD -- file/path/to/your/file

ця відповідь здається мені неправильною, оскільки вона б відкинула всі зміни, до file/path/to/your/fileяких не зверталась ОП, AFAIU
oromoiluig
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.