Як я можу витягнути один файл (або зміни у файл) із сховища git?


772

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

Чи може хтось міг дати деякі пропозиції щодо цього?

Відповіді:


1130

На сторінці " git stash" ви можете прочитати (у розділі "Обговорення", відразу після опису "Параметри"), що:

Схована скринька представлена ​​як команда, дерево якої записує стан робочого каталогу, а її першим батьківським елементом є команда в HEAD, коли створено копію.

Таким чином, ви можете ставитись до сховища (наприклад stash@{0}, перший / верхній сховище) як об'єднання об'єднань та використовувати:

$ git diff stash@{0}^1 stash@{0} -- <filename>

Пояснення: stash@{0}^1означає перший з батьків даного сховища, який, як зазначено в поясненні вище, є комітом, при якому зміни були приховані. Ми використовуємо цю форму "git diff" (з двома координатами), оскільки stash@{0}/ refs/stashє об'єднанням об'єднань, і ми повинні сказати git, з яким батьків ми хочемо відрізнятись. Більш криптовалюта:

$ git diff stash@{0}^! -- <filename>

також повинен працювати (див. сторінку git rev-розбору для поясненняrev^! синтаксису в розділі "Вказання діапазонів").

Так само ви можете використовувати git checkout, щоб перевірити один файл із сховища:

$ git checkout stash@{0} -- <filename>

або зберегти його під іншим іменем файлу:

$ git show stash@{0}:<full filename>  >  <newfile>

або

$ git show stash@{0}:./<relative filename> > <newfile>

( зауважте, що тут <повне ім'я файлу> - це повне ім'я файлу відносно верхнього каталогу проекту (думаю: відносно stash@{0})).


Ви , можливо , буде потрібно , щоб захистити stash@{0}від оболонки розширення, тобто використання "stash@{0}"або 'stash@{0}'.


8
Це досить круто ... Я не дуже розумів, як спрацьовував приховування, поки я не прочитав вашу відповідь (що веде мене до додатку до git-checkout). Я дійсно цього не зрозумів, коли ви робите приховану скриньку, git зберігає ДВІ зобов’язання - один для стану індексу та один для стану робочої копії, який є злиттям між індексом та оригінальною HEAD. Це пояснює дивні дерева, які я бачив, коли я візуалізував сховище "gitk --all", коли є присутні.
Пат Нотц

4
Здебільшого, я вважаю, що додаток на перевірку git є найкращим способом досягти того, що я хотів зробити. Однак мені було цікаво і двічі перевірили git checkoutсторінку чоловіка. Він не може перенести файл в інше місце. На це є посилання на: stackoverflow.com/questions/888414/…
Danny

84
$ git checkout приховування @ {0} - <ім'я файлу> дуже корисно, дякую
гравітація

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

4
Зауважте, що для git stash applyоб'єднання змін у файлі, який був змінений у робочому дереві з моменту зберігання файлу, цей файл у робочому дереві повинен бути інсценований. Щоб автоматичне злиття працювало, одні і ті ж файли не можуть бути змінені як у робочій копії, так і в прихованій копії для об'єднання копії. Нарешті, застосунок приховування не видаляє елемент із сховища, як git stash popхотілося.
Віль

46

Якщо ви використовуєте, git stash applyа неgit stash pop , він застосує приховану скриньку до вашого робочого дерева, але все одно збереже приховування.

Після цього ви можете add/ commitфайл, який ви хочете, а потім скинути решту змін.


2
Щоб вискочити конкретний тайник: git stash pop stash@{0}(Перерахуйте захованих зміни: git stash list)
MrYoshiji

Якщо інші файли в сховці викликають конфлікт злиття, git не дозволяє мені робити файл, який я хочу :(
cambunstiti

33

Існує простий спосіб отримати зміни з будь-якої галузі, включаючи скрині:

$ git checkout --patch stash@{0} path/to/file

Ви можете опустити специфікацію файлу, якщо ви хочете зробити виправлення у багатьох частинах. Або опустіть виправлення (але не шлях), щоб отримати всі зміни в одному файлі. Замініть номер 0на скриньку git stash list, якщо у вас їх більше. Зауважте, що це схоже diff, і пропонує застосувати всі відмінності між гілками. Щоб отримати зміни лише від однієї комісії / сховки, подивіться git cherry-pick --no-commit.


Чи копіює це точний файл із сховища чи він зливається? У разі копіювання, якщо ви змінилися з моменту створення сховища, вони будуть втрачені.
Даніель

2
@Danijel Read git help checkout. --patchробить інтерактивне злиття, застосовується все те, що ви схвалюєте в оболонці (або що ви збережете, якщо ви вирішите eвипустити патч). Сам шлях замінить файл, як я написав, "всі зміни".
Вальф

1
незначне поліпшення: git config --global alias.applydiffat '!git checkout --patch "$1" -- $(git diff --name-only "$1"^ "$1")' - тоді git applydiffat stash@{4}використовується лише файли, які змінилися між сховищем та його батьківським.
Марк

25

Коротка відповідь

Щоб переглянути весь файл: git show stash@{0}:<filename>

Щоб побачити різницю: git diff stash@{0}^1 stash@{0} -- <filename>


1
Я не думаю, що він / він не переймався переглядом сховища для певного файлу - лише вискакуючи цей файл.
Амальговінус

1
Це те, що я шукав. Потім ви можете замінити diffз difftoolвикористовувати ваш улюблений зовнішній диф.
Піет Брітс

19
$ git checkout stash@{0} -- <filename>

Примітки:

  1. Переконайтеся, що ви поставили пробіл після параметра "-" та імені файлу

  2. Замініть нуль (0) своїм конкретним номером скриньки. Щоб отримати список сховищ, використовуйте:

    git stash list
    

На основі відповіді Якуба Нарбського - Коротша версія


11

Ви можете отримати diff для сховища за допомогою " git show stash@{0}" (або будь-якої кількості скриньки; див. "Git stash list"). Вилучити розділ diff для одного файлу легко.


2
Ще простіший для розумів, як я: використовуйте, git show stashщоб показати найвищу сховку (як правило, єдину у вас є). Аналогічно ви можете показати різницю між вашою поточною гілкою і сховищем з git diff head stash.
Дізлі

5

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

Якщо ви все це git stashсховали, git stash applyповерніть їх знову, а потім git checkout f.cу відповідний файл, щоб ефективно скинути їх.

Коли ви хочете видалити цей запуск файлу, виконайте команду a, git reset --hardа потім запустіть git stash applyзнову, скориставшись тим фактом, git stash applyякий не очищає відмінність від стека.


1

Якщо сховані файли потрібно об'єднати з поточною версією, то використовуйте попередні способи, використовуючи diff. В іншому випадку ви можете використовувати їх git popдля видалення їх, git add fileWantToKeepдля постановки свого файлу, а також для того git stash save --keep-index, щоб зберігати все, крім того, що знаходиться на сцені. Пам'ятайте, що відмінність цього способу від попередніх полягає в тому, що він "вискакує" файл із сховища. Попередні відповіді зберігають цеgit checkout stash@{0} -- <filename> так, щоб він відповідав вашим потребам.


0

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

git diff stash^! -- <filename> | git apply

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


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