Повернути зміни до файлу у коміті


126

Я хочу повернути зміни, внесені певним комітетом, лише до заданого файлу.

Чи можу я використовувати для цього команду повернення git?

Будь-який інший простий спосіб це зробити?



Дивно ... чому зміна після всіх тих років?
VonC

Відповіді:


222

Найчистіша , як я бачив , робити це описано тут

git show some_commit_sha1 -- some_file.c | git apply -R

Схожа на відповідь VonC, але за допомогою git showта git apply.


10
Чудово зроблено. Рішення сценарію для цього є надмірним. Чому просто не може бути повернено ім'я файлу git sha-1?
Марк Едінгтон

16
Це працює на моєму Mac, але в Windows (під Cygwin) він дає мені:fatal: unrecognized input
Кедар Машадвад

1
@MerhawiFissehaye: Я думаю, що git checkout лише поверне зміни знову, щоб повернутись до того, що було в комітеті. Я додав ім'я файлу; git commit --amend ', щоб видалити файл з фіксації.
ViFI

3
Лише підказка, мені майже завжди доводиться додавати -3прапор до git, щоб застосувати для тристороннього злиття, коли патч виходить з ладу, оскільки я зазвичай виправляю зміни трохи за часом.
angularsen

2
Мабуть, очевидно для більшості, але гарантуйте, що some_file.cвключає шлях до файлу, якщо він є, інакше ви мовчки нічого не будете латати :)
Warpling

35

Якщо припустити, що змінити історію фіксації нормально, ось робочий процес для відновлення змін у одному файлі на попередньому фіксації:

Наприклад, ви хочете відновити зміни в 1 файлі ( badfile.txt) у коміті aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Повторіть базу на базовому комітеті, внесіть зміни в проблему і продовжуйте.

1) Запустіть інтерактивну базу даних:

git rebase -i aaa111

2) Позначте проблеми редагування для редагування в редакторі, змінивши pickна e(для редагування):

e aaa222
pick aaa333

3) Відновити зміни до поганого файлу:

git show -- badfile.txt | git apply -R

4) Додайте зміни та внесіть зміни:

git add badfile.txt
git commit --amend

5) Закінчіть ребауз:

git rebase --continue

Просто хочу зазначити, що це передбачає, що ви можете редагувати історію git. Деякі відповіді вище створюють нову команду, яка скасовує конкретну зміну без редагування історії, що не завжди можливо / дозволено.
angularsen

Фантастичний. Це саме те, що я шукав. Я вже мав цю ідею, але заплутався, коли робив інтерактивну базу даних, що файли при виконанні editне відображаються як змінені. Але відповідь git show -- badfile.txt | git apply -Rдав мені потрібну <3
mraxus

якщо я розумію, що цей git застосовується -R видаляє фіксацію цього файлу, повертаючи його до початкового зміненого стану?
DaImTo

19

git revert є для всього вмісту файлу в комітах.

Для одного файлу ви можете його скриптувати :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(З утиліт git-shell- script -скриптів від smtlaissezfaire )


Примітка:

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

git checkout -- filename

git checkout є деякі параметри для файлу, модифікуючи файл із HEAD, замінюючи зміни.


Dropped.on.Caprica в коментарях згадує :

Ви можете додати псевдонім до git, щоб ви могли це зробити git revert-file <hash> <file-loc>і повернути цей конкретний файл.
Дивіться цю суть .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh

Просто для додавання до дискусії тут ви можете додати псевдонім до git, щоб ви могли зробити git revert-file <hash> <file-loc>та повернути цей конкретний файл. Я відмовився від цієї відповіді (хоча мені довелося внести пару правок, щоб правильно працювати). Ви можете знайти копію мого .gitconfigта відредагованого сценарію тут: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB

@ Dropped.on.Caprica хороший момент. Я включив його у відповідь для більшої наочності.
VonC

12

Я б просто скористався --no-commitопцією, git-revertа потім видалити файли, які ви не хочете повернути з індексу, перш ніж остаточно зробити його. Ось приклад, який показує, як легко відновити лише зміни до foo.c у другій останній комісії:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

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


9

Набагато простіше:

git reset HEAD^ path/to/file/to/revert

тоді

git commit --amend   

і потім

git push -f

файл відсутній і введіть хеш, повідомлення тощо - те саме.


Для повноти вам потрібен git checkout -- path/to/file/to/revertкрок? Також не вірно, що і хеш згодом той самий, правда? Останнє речення може бути кращим як щось на кшталт: "Результат полягає в тому, що остання команда замінюється новою, яка відрізняється лише тим, що не містить змін у поверненому файлі."
Кевін

@Kevin ти мабуть прав. Мені доведеться ще раз перевірити цей останній рядок, але, озираючись на це ще пару років тому, я здивуюсь, якщо хеш-фікш не зміниться.
Форрест

6
git reset HEAD^ path/to/file/to/revert/in/commit

Вищевказана команда зніме файл з комісії, але відображатиметься в git status.

git checkout path/to/file/to/revert/in/commit

Наведена вище команда відновить зміни (в результаті ви отримаєте файл такий же, як HEAD).

git commit

(Перейдіть --amendдля внесення змін до комісії.)

git push

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

Вищезазначені кроки слід виконувати з гілки, де здійснюється комісія.


5

Ви можете дотримуватися цієї процедури:

  1. git revert -n <*commit*>( -nвідновіть усі зміни, але їх не буде здійснено)
  2. git add <*filename*> (назва файлу / файлів, який ви хочете відновити та ввести)
  3. git commit -m 'reverted message' (додайте повідомлення для повернення)
  4. після введення скасування інші зміни файлів змінюються, щоб вони залишалися в курсі змін, які ви здійснили до відновлення

1

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

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

git checkout <prev_commit_hash> -- <path_to_your_file>

Сподіваюся, це допомагає :)

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