как просмотреть неотслеживаемые файлы, которые были "git stash -u" - PullRequest
0 голосов
/ 16 сентября 2018

Хранение контента в git очень полезно. когда вы сохраняете файлы и следите за этим, как это

echo test > foo
git stash -u # foo is stashed
git stash show -p stash@{0}

неотслеживаемые файлы не отображаются. как мы можем их увидеть?

спасибо

1 Ответ

0 голосов
/ 16 сентября 2018

Вам просто нужно взглянуть на третий коммит.Но «просто нужно» немного преуменьшает значение, и это не имеет никакого смысла, пока вы не узнаете, что из трех коммитов есть .Чтобы понять, что я имею в виду, читайте дальше.

Настройка: что нужно знать о тайниках

Когда вы запускаете git stash save или git stash push, обычным действием Git является создание two коммитов, ни один из которых не находится ни на одной ветви.Если вы нарисуете картинку «до», как это, вы получите следующую серию коммитов:

...--o--o--*   <-- branch (HEAD)

После завершения git stash save у вас будет два новых коммита, которые не находятся на веткеbranch и не в любой другой ветви:

...--o--o--*   <-- branch (HEAD)
           |\
           i-w   <-- the stash

Фиксация w сохраняет состояние рабочего дерева, в то время как фиксация i сохраняет индекс.Каждый из этих двух коммитов очень похож на любой другой коммит, и фактически фиксация i выполняется с использованием большей части обычного механизма git commit: Git записывает текущий индекс во внутренний объект tree используя git write-tree, затем создает commit объект, используя git commit-tree.Если вы не знаете, что это за внутренние объекты, не беспокойтесь об этом: дело в том, что именно так git commit выполняет большую часть своей работы, записывая дерево, а затем объект фиксации.(Остальная часть git commit состоит в том, чтобы сначала собрать ваше лог-сообщение и обновить имя ветки в конце.)

Коммит w немного сложнее, потому что он имеет форму (но не намерение) коммита merge с двумя родителями вместо одного.Но в основном он сохраняет снимок рабочего дерева, как если бы вы запустили git add для всех отслеживаемых файлов.

При добавлении --all или --include-untracked (-a или -uдля краткости), что делает git stash, так это то, что он добавляет третий коммит, который мы можем нарисовать следующим образом:

...--o--o--*   <-- branch (HEAD)
           |\
           i-w   <-- the stash
            /
           u

Третий коммит является снимком, но этоочень странный снимок.Он содержит только неотслеживаемых файлов - либо неотслеживаемых, но не игнорируемых файлов (git stash save -u), либо неотслеживаемых файлов , включая неотслеживаемых и игнорируемых файлов (* 1058)*).У него также нет родительского коммита.

стека "stash", хеш-идентификаторов коммитов и родителей

Одна причина 1 , что Git добавилpush глагол, как в git stash push - который в целом является синонимом save - это то, что когда вы создаете новый тайник, Git использует тайник reflog для отслеживания более ранних тайников.Текущий тайник stash@{0} в терминах reflog, а ранний тайник становится stash@{1}.

Каждое из этих имен является лишь частным случаем более общей вещи, которую дает вам Git: вы можете ссылаться на любойЗафиксируйте любое имя, которое соответствует правильному хэш-идентификатору .«Истинное имя» любого коммита - это его большой уродливый хэш-идентификатор. Документация gitrevisions содержит полное описание всех способов написания хэш-идентификатора в Git;использование имени, такого как branch или stash, является одним из таких способов.

Использование имени stash специально определяет фиксацию w.Затем Git использует w для поиска коммита i и, если он существует, коммит u.Git может сделать это, потому что каждый коммит включает хэш-идентификаторы его parent commits.w имеет форму коммита слияния в том, что у него есть как минимум два родителя: i, индексный коммит и *, коммит, на котором вы сидели, когда запускали git stash save или git stash pushво-первых.

Мы можем модифицировать большинство спецификаторов ревизий (например, stash), добавив символ вставки ^ и число, чтобы посмотреть конкретно на пронумерованного родителя.Запись stash^1 - это способ фиксации именования *;запись stash^2 - это способ присвоения имен фиксации i.Если коммит u существует, запись stash^3 дает ему имя.Обратите внимание, что в некоторых системах (Windows) ^ может быть специальным символом, который требует удвоения или цитирования, поэтому вместо stash^3 вам может понадобиться stash^^3.


1 Другая причина заключалась в том, чтобы добавить возможность частичного сохранения с использованием pathspecs: git stash save принимала любые дополнительные аргументы в качестве сообщения для включения в коммиты stash, поэтому им был нужен новый глагол, который использовал -mчтобы указать сообщение, оставляя место для аргументов pathspec.


Просмотр u commit

Мы можем просмотреть любой коммит, используя git show.Поскольку stash w фиксирует это осечки, потому что Git считает, что коммит w является слиянием, поэтому мы можем использовать git stash show вместо этого.(Это - это слияние, просто не то, которое git show может показать правильно.) Мой более ранний ответ на связанный вопрос требует использования git diff в коммите u,потому что в данном конкретном случае мы не хотим получать заголовок, который показывает git show, но если мы просто хотим посмотреть фиксированный файл, то можно использовать git show здесь:

git show stash^3

например.Вот вывод для приведенного выше примера foo:

$ git show stash^3
commit 4c9bd2486706980f5a492d19c49270381db2d796
Author: Chris Torek <chris.torek gmail.com>
Date:   Sun Sep 16 12:35:03 2018 -0700

    untracked files on master: f72737e initial

diff --git a/foo b/foo
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+foo

Использование имени наподобие stash@{1} идентифицирует коммит в записи reflog # 1, которая является следующей копью в вашем "стэке стека".(Reflog начинает отсчет с нуля, поэтому stash и stash@{0} означают один и тот же коммит.) Так что для stash@{1} вам потребуется stash@{1}^3 или, возможно, stash@{1}^^3.

...