Git diff против тайника

1361

Как я могу увидеть изменения, внесенные без сохранения в текущее рабочее дерево? Я хотел бы знать, какие изменения будут внесены, прежде чем их применять!

Джеймс
источник
1
Связанный пост здесь .
RBT

Ответы:

1874

Смотрите самые последние тайники:

git stash show -p

Смотрите произвольный тайник:

git stash show -p stash@{1}

Из git stashсправочных страниц:

По умолчанию команда показывает diffstat, но она принимает любой формат, известный для git diff (например, git stash show -p stash @ {1} для просмотра второго самого последнего хранилища в форме патча).

янтарный
источник
72
stash@{0}по умолчанию; вам нужен только аргумент, если вы хотите посмотреть на предыдущие тайники.
Каскабель
52
Правильно. Я просто поставил его, чтобы было ясно, как смотреть на другие тайники {0}.
Январь
74
Это не покажет разницу между тайником и текущим рабочим каталогом, но между тайником и его исходным родителем. Правильно? Из справочной страницы: «Показать изменения, записанные в тайнике, в виде различий между сохраненным состоянием и его исходным родителем».
Магне
14
@Amber - Правда, хотя если ваше текущее рабочее дерево грязное, это имеет значение, и делает его немного сложнее. Я пришел к этому с этой точки зрения и нашел процедуру, которой я поделился в своем ответе ниже.
Магне
6
что означает -pстенд?
Джеральд
308

Чтобы увидеть самые последние тайники:

git stash show -p

Чтобы увидеть произвольный тайник:

git stash show -p stash@{1}

Также я использую git diff для сравнения тайника с любой веткой.

Ты можешь использовать:

git diff stash@{0} master

Чтобы увидеть все изменения по сравнению с филиалом мастера.


Или Вы можете использовать:

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

Чтобы легко найти только измененные имена файлов.

czerasz
источник
10
Это не отвечает на конкретный вопрос. Если вы создали тайник от мастера (чтобы сохранить работу на потом), затем выполните некоторые коммиты для другой работы над мастером, а затем git diff stash@{0} masterполучите различие вашего тайника с текущим мастером (которое включает в себя работу, выполненную на мастере после тайника было сделано), а не файлы / строки, которые изменил бы тайник, о чем вопрос.
Том Де Лей
52
Я рад, что вы ответили на вопрос, даже если это не был ответ на точный вопрос. Это дало больше информации, и я думаю, это здорово знать, как получить разницу между веткой и любой другой веткой, с которой вы хотите сравнить. Мне также понравилось изучать флаг
Ревекка Уотербери
6
это также позволяет взглянуть на различия с помощью специального средства просмотра различий, например,git difftool --tool=... stash@{0} HEAD
Andre Holzner
9
@TomDeLeu Хорошее наблюдение и важный момент. Для сравнения тайника с его родителем, это, кажется, работает:git diff stash@{0}^ stash@{0}
erikprice
1
Кроме того, вы можете добавить имя файла, git diff stash@{0} master -- filenameчтобы получить изменения в конкретном файле.
Дэвид
104

Если ветвь, на которой основаны ваши спрятанные изменения, за это время изменилась, эта команда может быть полезна:

git diff stash@{0}^!

Это сравнивает тайник с коммитом, на котором он основан.

t.heintz
источник
так хорошо, что я добавил псевдоним ~/.gitconfig:laststash = diff stash@{0}^!
sbeam
5
Идеальная пара: git difftool stash^!для сравнения последнего тайма с коммитом, на котором он основан, git difftool stash HEADдля сравнения последнего тайма с текущим коммитом (stash @ {n} для более ранних тайников)
ChrisV
17
Для тех, кто был похож на меня и никогда не видел ^! до: совершить ^! это спецификатор диапазона, который означает: этот коммит, но не его родитель.
Джонатан Гаврич
"git diff stash @ {0} ^!" сводится к "git diff stash @ {0} ^ stash @ {0} ~ 1 ^ stash @ {0} ~ 2 .......", но, поскольку git diff занимает только 2 коммита, он показывает разницу между stash @ {0} и ^ stash @ {0} ~ 1 и смотрит на ^ в начале второго коммита, ничего не меняет и git игнорирует это.
Нага Киран
Я предпочитаю, чтобы эта версия могла использовать мой предпочтительный инструмент сравнения (конечно, за пределами!). Это также показывает изменение в этом тайнике, который, как я полагаю, является первоначальным вопросом, в отличие от альтернативы, упомянутой в приведенных выше комментариях "git diff stash @ {X} ^ stash @ {X}", которая показывает больше, чем просто скрытый дифференциал.
user107172
44

Если ваше рабочее дерево грязное , вы можете сравнить его с тайником, сначала зафиксировав грязное рабочее дерево, а затем сравнив его с тайником. После этого вы можете отменить коммит с грязным рабочим деревом (так как вы можете не захотеть иметь этот грязный коммит в вашем журнале коммитов).

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

  • Передайте свое грязное рабочее дерево:

    git add .
    git commit -m "Dirty commit"
    
  • Diff тайник с этим коммитом:

    git diff HEAD stash@{0}
    
  • Затем, после этого, вы можете отменить коммит и вернуть его в рабочий каталог:

    git reset --soft HEAD~1
    git reset .
    

Теперь вы разобрали грязное рабочее дерево со своим тайником и вернулись к тому месту, где были изначально.

Магне
источник
Есть ли способ сделать это, но только увидеть различия файлов, которые будут изменены тем, что находится в тайнике?
Lagweezle
В 2020 году это намного проще; проверьте мой актуальный ответ .
Дэвид Депрост
Интересно, я не знал о git stash show -l . Различает ли последний тайник рабочую (грязную) копию? Как вы используете это, не получая error: switch l requires a value?
Магне
Да, действительно, он отличается от (возможно, грязной) рабочей копии. Вы используете это просто введя git stash show -l. Что касается того, почему это не работает для вас, я могу только догадываться, что вы можете использовать более старую версию git? Я на git v2.20.1, и работает без нареканий без ошибок.
Дэвид Депрост
25

@ Ответ Магне - единственный, который (очень поздно) встречается, чтобы ответить на наиболее гибкую / полезную интерпретацию вопроса, но он немного сложнее, чем необходимо. Вместо фиксации и сброса просто спрячьте свою рабочую копию, сравните, а затем распакуйте.

git stash save "temp"
git diff stash@{0} stash@{1}
git stash pop

Это показывает разницу между вершиной стека stash и вашей рабочей папкой, временно делая изменения рабочей папки стать вершиной стека stash (stash @ {0}), перемещая исходную верхнюю часть вниз на одну (stash @ {1} ) затем сравнивая, используя исходную вершину в позиции «новый набор», чтобы увидеть изменения, которые могут возникнуть в результате применения ее поверх текущей работы.

"Но что, если у меня нет текущей работы?" Тогда вы в нормальном скучном деле. Просто используйте ответ @ Amber

git stash show

или ответ @ czerasz

git diff stash@{0}

или признать, что копить и расстегивать быстро и легко в любом случае, просто распакуйте изменения и осмотрите их. Если вы не хотите, чтобы они в данный момент выбрасывались (текущий индекс / рабочая папка меняется). В полном объеме это

git stash apply
git diff
git reset
git checkout
SensorSmith
источник
3
Этот простой подход (копить, а затем сравнить с другим тайником) безопасен и прост для понимания. В некоторых случаях вы можете также сохранить неотслеживаемые файлы сgit stash save -u
mleonard
19

Это работает для меня на git версии 1.8.5.2:

git diff stash HEAD
Rimian
источник
2
Вводя в заблуждение! Вопрос заключается в следующем: как я могу увидеть, какие изменения будут сделаны без сохранения в текущем рабочем дереве? Это показывает разницу между тайником и ГОЛОВКОЙ, которая может ОЧЕНЬ отличаться от той, которая будет применяться git stash apply.
MikeJansen
Пожалуйста, ознакомьтесь с вопросом «Я хотел бы знать, какие изменения будут внесены перед их применением!». Я даю быстрый ответ на это.
yerlilbilgin
Также вы можете видеть, что все остальные ответы как-то касаются различий текущей головы (или рабочего набора) против тайника. Почему только мой ответ вводит в заблуждение? Это не честно.
yerlilbilgin
@yerlilbilgin Смотрите мой ответ на ваш ответ ниже.
MikeJansen
Мы можем опустить HEAD, это по умолчанию, не так ли?
Ал.Г.
10

На всякий случай, чтобы сравнить файл в рабочем дереве и в тайнике, используйте команду ниже

git diff stash@{0} -- fileName (with path)
Прамод БР
источник
9

Если у вас есть инструменты для сравнения (например, вне всякого сравнения)

git difftool stash HEAD
yerlilbilgin
источник
1
Вводя в заблуждение! Вопрос заключается в следующем: как я могу увидеть, какие изменения будут сделаны без сохранения в текущем рабочем дереве? Это показывает разницу между тайником и ГОЛОВКОЙ, которая может ОЧЕНЬ отличаться от той, которая будет применяться git stash apply.
MikeJansen
1
Если вы считаете, что это вводит в заблуждение, проверьте все остальные ответы. Это не честно!
yerlilbilgin
1
Вы заметите, что я скопировал тот же комментарий к другому ответу, который также вводил в заблуждение (почти тот же ответ). Другие ответы, которые уже имели подобный комментарий, я оставил один. Если вы поймете, как работает git stash, то вы поймете, что изменение хранилища против HEAD - это не то, что применяется (о чем просит OP). Фактический «тайник» - это разница между коммитом и тем, что было до него. Этот патч затем применяется к голове. Поэтому, если вы хотите знать, что запросил OP, вы должны показать разницу между тайником и коммитом перед ним, что и делают правильные ответы.
MikeJansen
1
Это отвечает на вопрос более прямо, чем любой из других (ненужных) длинных ответов, и делает в точности то, что спросил ОП, за исключением удаления HEAD. Я мог бы изменить ответ @ yerlilbilgin, чтобы удалить HEAD, но я думаю, что любой, кто использует git, может понять эту часть, и если я удлиню ответ, это сделает его менее читабельным. Нет вины на @yerlibilgin.
Шридхар Сарнобат
4

Один из способов сделать это, ничего не перемещая, - воспользоваться тем, что patchможет читать git diff (в основном, unified diff)

git stash show -p | patch -p1 --verbose --dry-run

Это покажет вам пошаговый предварительный просмотр того, что обычно делает патч. Дополнительным преимуществом этого является то, что патч не помешает самому записать патч в рабочее дерево, если по какой-то причине вам просто нужен git, чтобы замолчать о коммитах перед изменением, продолжайте и удалите --dry- бегите и следуйте подробным инструкциям.

xenithorb
источник
2

Объединяя то, что я узнал в этой теме и в этой , когда я хочу увидеть «что находится в тайнике», я сначала запускаю:

git stash show stash@{0}

Это покажет, какие файлы были изменены. Затем, чтобы получить хороший визуальный diff в difftool, я делаю:

git difftool --dir-diff stash@{0} stash@{0}^

Это покажет все различия сразу данного тайника против его родителя.

Вы можете настроить инструмент сравнения ~/.gitconfig, например, с помощью Meld :

...
[diff]
    tool = meld
Ferrard
источник
1

FWIW Это может быть немного избыточно для всех других ответов и очень похоже на принятый ответ, который является точным; но, возможно, это поможет кому-то.

git stash show --helpдаст вам все, что вам нужно; включая информацию о тайнике.

показать [<stash>]

Показать изменения, записанные в хранилище, в виде различий между сохраненным состоянием и его исходным родителем. Когда нет, показывает последний. По умолчанию команда показывает diffstat, но она принимает любой формат, известный для git diff (например, git stash show -p stash @ {1} для просмотра второго самого последнего хранилища в форме патча). Вы можете использовать переменные конфигурации stash.showStat и / или stash.showPatch, чтобы изменить поведение по умолчанию.

Rockin4Life33
источник
1

Она список заначки

git stash list 
stash@{0}: WIP on feature/blabla: 830335224fa Name Commit
stash@{1}: WIP on feature/blabla2: 830335224fa Name Commit 2

Так что получите номер тайника и сделайте:

Ты можешь сделать:

 git stash show -p stash@{1}

Но если вам нужен diff (это другое, чтобы показать тайник, поэтому я пишу этот ответ. DiffРассмотрите текущий код в вашей ветке и showпросто покажите, что вы будете применять )

Ты можешь использовать:

git diff stash@{0}

или

git diff stash@{0} <branch name>

Еще одна интересная вещь:

git stash apply
git stash apply stash@{10}

Это применяет тайник, не удаляя его из списка, вы можете git checkout .удалить эти изменения или, если вы счастливыgit stash drop stash@{10} удалить тайник из списка.

Отсюда я никогда не рекомендую использовать git stash popи использовать комбинацию git stash applyи git stash dropесли вы примените тайник в неправильной ветке ... ну, иногда трудно восстановить ваш код.

Рауль Мартин
источник
1

В зависимости от того, с чем вы хотите сравнить тайник (локальное рабочее дерево / родительский коммит / главный коммит), на самом деле доступно несколько команд, среди которых старая git diffи более конкретная git stash show:

╔══════════════════════╦═══════════════════════════════╦═══════════════════╗
║ Compare stash with ↓ ║ git diff                      ║ git stash show    ║
╠══════════════════════╬═══════════════════════════════╬═══════════════════╣
║ Local working tree   ║ git diff stash@{0}            ║ git stash show -l ║
║----------------------║-------------------------------║-------------------║
║ Parent commit        ║ git diff stash@{0}^ stash@{0} ║ git stash show -p ║
║----------------------║-------------------------------║-------------------║
║ HEAD commit          ║ git diff stash@{0} HEAD       ║   /               ║
╚══════════════════════╩═══════════════════════════════╩═══════════════════╝

Хотя git stash showна первый взгляд выглядит более удобным для пользователя, на git diffсамом деле он более мощный, поскольку позволяет задавать имена файлов для более сфокусированного сравнения. Я лично настроил псевдонимы для всех этих команд в своем плагине zsh git .

Дэвид Депрост
источник