git diff $sha1..$sha1^
создает патч, который отменяет коммит $sha1
(в нем перечислены различия между этим коммитом и его родителем). Если указан $file
, этот патч ограничивается изменениями, внесенными в $file
в данной фиксации.
Этот патч затем загружается в patch -p1
, который удаляет поддельные имена каталогов, используемые git
(a/
и b/
) и попытаться применить исправление к любым файлам, перечисленным в исправлении (т.е. , $file
, если он был назван и изменен в данной фиксации, или ко всем файлы, измененные в данной фиксации, включая файлы в подкаталогах). Если файлы, присутствующие в текущем каталоге и его подкаталогах, существенно отличаются (или, по расширению, отсутствуют), patch
не сможет применить патч.
Это стало возможным благодаря тому, что патчи в унифицированном формате, создаваемые git diff
(и diff -u
), включают имена исправляемых файлов и контекст для патча. Вот пример (не из git
, но он показывает идею):
diff -ur cli-common-0.9+nmu1.orig/policy-remove cli-common-0.9+nmu1/policy-remove
--- cli-common-0.9+nmu1.orig/policy-remove 2015-02-25 21:34:08.000000000 +0100
+++ cli-common-0.9+nmu1/policy-remove 2017-04-08 20:47:09.029065259 +0200
@@ -11,4 +11,4 @@
#echo "Removing GAC policy file ($POLICY) from available GACs"
/usr/share/cli-common/gac-package-remove $POLICY > /dev/null
-rm /usr/share/cli-common/packages.d/$POLICY.installcligac
+rm -f /usr/share/cli-common/packages.d/$POLICY.installcligac
Этот патч говорит, что он модифицирует файл с именем cli-common-0.9+nmu1.orig/policy-remove
, чтобы создать файл с именем cli-common-0.9+nmu1/policy-remove
. Само изменение начинается со строки 11 и занимает 4 строки, включая контекст (это @@ -11,4
); в мишени измененные строки находятся в той же позиции (+11,4 @@
).Над изменением есть три строки контекста, затем само изменение, удаление строки, начинающейся с rm
, и добавление строки, начинающейся с rm -f
. Когда patch
применяет это, он будет искать файл с соответствующим именем (после удаления компонентов пути, если это указано с опцией -p
), и сравнивать контекст в файле с пластырь; изменение будет применено только в том случае, если контекст совпадает (в пределах нескольких строк, в зависимости от опций фаззинга).
Весь смысл этого скрипта в том, чтобы попытаться отменить изменения, сделанные в одном файле в данном коммите (отсюда и его название). Возможно это или нет, зависит от изменений, внесенных в файл после этой фиксации; но это часто весьма полезно на практике. (Чтобы отменить полную фиксацию, вы должны вместо этого использовать git revert
.)
В большинстве оболочек символ "*" не совпадает с начальным "." по историческим причинам (например, файлы, начинающиеся с ".", считаются скрытыми, а "." & ".." относятся к каталогам)
Следовательно ls
не будет отображать .bashrc, но ls -a
покажет все файлы.
Точно так же ls *
расширится на все файлы, кроме тех, которые начинаются с "." персонаж.
Измените это поведение с помощью shopt -s dotglob
, который сообщает bash, что "*" также должно соответствовать начальному "." символ.
После этого ls *
также покажет .bashrc.
Причина в том, что первая точка - это соглашение для «скрытого файла» и подстановки файлов (это имя для использования *
как «любое количество любых символов» и ?
как «любой один символ» и несколько других) специально исключает начальную точку, потому что это означает «скрытый файл».
Если вы напишете ls -l. *
, вы получите соответствие .bashrc
, но вы также будете соответствовать специальным скрытым файлам .
и ..
, которые являются каталогами, поэтому для отображения скрытых файлов вам понадобится что-то вроде этих строк:
ls -ld. *
ls -l. [^.] *
LS-A | grep bash
ls -A * bash *
не покажет вам .bashrc
, потому что подстановка файлов выполняется до того, как вступит в силу параметр -A
.
Если вы хотите изменить способ подстановки файлов со скрытыми файлами, вы можете выполнить shopt -s dotglob
, либо просто в оболочке для тестирования, либо вставьте в свой.bash_profile или .bashrc, чтобы он всегда был эффективным.
Опция оболочки dotglob
управляет этим:
$ shopt -s dotglob
$ ls *bash*
.bash_history .bash_logout .bashrc
Она не включена по умолчанию, вероятно, в качестве меры удобства/безопасности, поскольку большинство конечных пользователей не беспокоятся о dotfiles и могут легко удалить критические файлы домашнего каталога (такие как .config
, .ssh
) случайно.