Як я можу відмовити віддалені зміни та позначити файл як "вирішений"?


197

У мене є локальні файли, я витягую з віддаленої гілки і виникають конфлікти. Я знаю, що хотів би зберегти свої локальні зміни та ігнорувати віддалені зміни, що викликають конфлікти. Чи є команда, якою я можу фактично сказати «позначити всі конфлікти як вирішені, використовувати локальні»?


1
Відповідь нижче була для мене надзвичайно яскравою. Є кілька тонких моментів, які дійсно зрозуміли для мене речі, я рекомендую будь-яким непрофесійним користувачам GIT прочитати всі коментарі під публікацією нижче, і дякую Брайану!
Том ДеМіль

Відповіді:


332

git checkoutє --oursможливість перевірити версію файлу, який ви мали локально (на відміну --theirsвід версії, яку ви втягнули). Ви можете перейти .до того, git checkoutщоб сказати, щоб перевірити все на дереві. Тоді вам потрібно позначити конфлікти як вирішені, що ви можете зробити git add, і виконати свою роботу після закінчення:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

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

Це також хороша звичка при передачі імені файлу компенсувати його --, наприклад git checkout --ours -- <filename>. Якщо ви цього не зробите, а ім'я файлу збігається з назвою гілки або тегу, Git подумає, що ви хочете перевірити цю версію, а не перевіряти це ім'я файлу, і тому використовувати першу форму checkoutкоманди .

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

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

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

Тоді ви потрапляєте в ситуації, в яких насправді потрібно злити два зміни. У цьому випадку можливі два результати. Одне полягає в тому, що злиття відбувається чисто; всі зміни є в різних файлах або в одних і тих же файлах, але досить далеко, крім того, що обидва набори змін можна застосувати без проблем. За замовчуванням, коли відбувається чисте злиття, воно автоматично виконується, хоча ви можете відключити це, --no-commitякщо вам потрібно заздалегідь відредагувати його (наприклад, якщо ви перейменовуєте функцію fooна bar, а хтось ще додає новий код, який викликає foo, він злиється чисто , але створіть зламане дерево, тож ви, можливо, захочете очистити це як частина комісії злиття, щоб уникнути будь-яких зламаних коміктів).

Остаточна можливість полягає в тому, що відбувається справжнє злиття, і виникають конфлікти. В цьому випадку Git буде робити стільки злиття , як він може, і створювати файли з маркерами конфліктів ( <<<<<<<, =======і >>>>>>>) у вашій робочої копії. У індексі (також відомому як "область постановки"; місце, де зберігаються файли git addдо їх створення), ви матимете 3 версії кожного файлу з конфліктами; є оригінальна версія файлу від предка двох гілок, з якими ви зливаєтеся, версія від HEAD(з вашого боку об'єднання) та версія з віддаленої гілки.

Щоб вирішити конфлікт, ви можете або відредагувати файл, який є у вашій робочій копії, видаливши маркери конфлікту та зафіксувавши код так, щоб він працював. Або ви можете перевірити версію з тієї чи іншої сторони об’єднання, використовуючи git checkout --oursабо git checkout --theirs. Після того, як ви помістите файл у потрібний вам стан, ви вказуєте, що ви зробили об'єднання файлу, і він готовий здійснити використання git add, і потім ви можете здійснити злиття git commit.


7
Вам, мабуть, слід зауважити, що git add --allвсі файли додаються до сховища, тому це може додати більше файлів, ніж передбачалося, якщо тільки ваші .gitignoreшаблони не знаходяться в ідеальному стані. git add -uМабуть, більше підходить для цієї ситуації, ви менше шансів змінити відстежені файли, які ви не хочете додати під час вирішення об'єднання.
CB Bailey

На жаль, вибачте. Це я мав на увазі. Виправлено це зараз.
Брайан Кемпбелл

1
дякую за детальну відповідь. Насправді я спробував перевірити git checkout - свої і отримав повідомлення про помилку (якого зараз не пригадую). Файли, про які йдеться, dll (у нас є декілька, які ми робимо приховування, здебільшого сторонні посилання), і я хотів просто сказати "добре, моя копія - це те, що я хочу, але помилка була чимось на кшталт" не можу перевірити під час злиття " ..... Я збережу цю статтю в якості посилання, і наступного разу, коли це станеться, спробуйте її ще раз і побачу, чи працює вона чи чи можу я опублікувати це повідомлення. Ще раз дякую
Том ДеМіль

але ваше пояснення для мене багато чого пояснює процес, ще раз дякую ... Подальше запитання: Будь-який спосіб отримати git для видалення .orig файлів, коли я злиття очиститься?
Том Деміл

2
Вам потрібно зробити git checkout --ours .. Важливе .значення; передаючи ім'я файлу (в даному випадку весь каталог), вибирає два різних режими роботи checkout, той, який перемикає гілки, і той, який переміщує файли з індексу в робочу копію. Я згоден, це дуже заплутано. Ви також можете одночасно git checkout --ours -- <filename>перевірити окремий файл.
Брайан Кемпбелл

23

Переконайтеся походження конфлікту: якщо це результат git merge, см Брайан Кемпбелл «s відповідь .

Але якщо це результат git rebase, щоб відкинути віддалені (їх) зміни та використати локальні зміни, вам слід зробити:

git checkout --theirs -- .

Див. " Чому значення" ours"та" theirs"повернено" ", щоб побачити, як oursі theirsзмінюються місцями під час перезавантаження (тому що перевірена гілка вище ).

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