Git: перетащите файл в тайник, не применяя его

Я удивлен, что не нашел ответа на этот вопрос, но в основном говорю, что у меня есть тайник с несколькими файлами (например, я могу изучить его через расширение git). Глядя на его содержимое, я хотел бы скинуть несколько файлов перед его применением, возможно ли это?

Единственное обходное решение, о котором я могу думать, это:

  1. проверить тайник в новую ветку
  2. проверить целевые файлы
  3. копить снова
  4. удалить ветку

Есть что-то лучше?

Благодарность


person ClementWalter    schedule 03.05.2017    source источник


Ответы (4)


Вы можете напрямую использовать stash@{0} в качестве ссылки на коммит.

Если ваше рабочее дерево чистое (без измененных файлов), вы можете извлечь нужные файлы:

git checkout stash@{0} -- file1 file2 file3

а затем проверьте diff вручную, чтобы сохранить то, что вы хотите.


Если вы хотите что-то более близкое к поведению git stash apply, вы можете создать патч и применить его:

git show -p stash@{0} -- file1 file2 file3 | git apply -

[EDIT] Чтобы перечислить файлы, измененные в stash@{0}:

git diff --name-only stash@{0}^ stash@{0}

Если вы хотите получить все файлы, кроме одного:

git show -p stash@{0} -- $(git diff --name-only stash@{0}^ stash@{0} |\
                           grep -v "thefile")
person LeGEC    schedule 03.05.2017
comment
git потрясающий, спасибо. Это отлично подходит для того, что он делает, но не изменяет тайник. Скажем, я хочу применить все файлы, кроме одного, я должен перечислить их все. Есть ли какая-то противоположная команда? - person ClementWalter; 03.05.2017
comment
Я не могу заставить git show -p stash@{0} -- file1 file2 file3 | git apply - работать, я получил ошибку: нераспознанный ввод, хотя он работает без | git apply - - person ClementWalter; 03.05.2017
comment
Это работает: вы имеете в виду, что git show -p ... > patch && git apply patch работает? - person LeGEC; 03.05.2017

Да, есть лучший способ сделать это.

Прежде всего, вы можете проверить список тайников как

git stash list

Затем вы можете сделать ниже для проверки содержимого спрятанных коммитов.

git stash show -p stash@{1}

Затем вы можете подать заявку, используя

git stash apply stash@{1}
person FallAndLearn    schedule 03.05.2017
comment
спасибо, но это не ответ на мой вопрос. Я знал, как увидеть содержимое тайника и применить его глобально. Я искал своего рода частичное применение тайника, см. Ответ @LeGEC - person ClementWalter; 03.05.2017

Кажется, что сложная часть этого вопроса вращается вокруг того, как вы хотите, чтобы тайник выглядел, когда вы закончите. Поскольку git stash {pop|apply} влияет только на рабочее дерево (а иногда и на индекс), достаточно просто выборочно брать изменения из тайника (достаточно, чтобы я сначала подумал, что вы слишком много думаете о проблеме):

git stash pop
# maybe a 'git reset head' if the index was changed
git checkout -- file.with.unwanted.changes.in.stash

Но эти команды полностью удаляют тайник; и, напротив, если бы я сказал git stash apply вместо pop, тайник останется без изменений. Похоже, вы хотите, чтобы тайник оставался с выбранными вами изменениями (на случай, если вам понадобится применить их снова).

(Я полагаю, что могут быть случаи, когда вы захотите прямо противоположного — оставить в тайнике те изменения, которые вы не применили, чтобы их можно было применить позже.)

Итак, делаем шаг назад: что связано с модификацией тайника?

На самом деле тайник состоит из двух или трех временных коммитов. Специальная ссылка stash указывает на эти коммиты, а "стек" из нескольких тайников поддерживается с помощью reflog (что может быть чем-то вроде хака, но в целом эффективно).

Таким образом, чтобы изменить тайник, нужно создать новые коммиты (поскольку коммиты неизменяемы) и соответствующим образом изменить порядок stash ref и reflog.

Вот почему обозначения, которые упоминает LeGEC, будут работать и могут дать вам дополнительную гибкость при чтении тайника. Но поскольку использование reflog не такое же, как для ссылок без тайника, использование этого факта для изобретения способа записи в тайник может привести к неожиданным результатам. Я не говорю, что результаты будут ужасными или их невозможно предсказать/контролировать; но я думаю, что в конце концов вы создадите больше сложности, чем избежите.

Итак, если мы ограничимся фактическими задокументированными git-stash подкомандами, то тайник будет более или менее атомарным. Когда вы создаете тайник, есть режим patch, который позволяет вам выбирать рабочие изменения для помещения в стек, но мне не известно о соответствующей функциональности для всплывающего/применения. Тем не менее, это что-то:

Если у вас есть чистое рабочее дерево и тайник, который вы хотите разделить, вы можете попробовать такие вещи, как:

Применить некоторые изменения и сохранить те же самые изменения в тайнике

git stash pop
git stash -p
# select the "good" changes
git checkout -- .
git stash apply

Применить некоторые изменения, а остальные оставить в тайнике

git stash pop
git stash -p
# select the "unwanted" changes

Разделите тайник на две части, решите, что с ними делать позже

git stash pop
git stash -p
# select the "good" changes
git stash
# now the "good" changes are stash@{1} and the "unwanted" are stash@{0}
person Mark Adelsberger    schedule 03.05.2017
comment
Небольшое техническое примечание: каждый тайник всегда состоит как минимум из двух коммитов (состояние индекса плюс состояние рабочего дерева), а иногда и из трех: индексного, рабочего дерева и дополнительного. Дополнительная часть присутствует в тайниках git stash -u или git stash -a и содержит неотслеживаемые-без-игнорированные или неотслеживаемые-включающие-игнорированные файлы (только; это не похоже на состояния индекса и рабочего дерева, которые сохраняют все отслеживаемые файлы). - person torek; 03.05.2017
comment
@torek - Ха ... по какой-то причине я думал, что если бы одно или другое было пустым, оно было бы опущено. Будет обновляться. Спасибо. - person Mark Adelsberger; 03.05.2017

Простое решение для удаления записи в тайнике без ее применения — удалить ее:

git stash drop stash@{1}

Здесь 1 — это запись тайника, которую вы получите, запустив:

git stash list
person YetAnotherBot    schedule 27.11.2019