要在提交中恢复对文件的更改,请从https://stackoverflow.com/a/2620822/156458
#!/bin/bash
function output_help {
echo "usage: git-revert-single-file <sha1> <file>"
}
sha1=$1
file=$2
if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi
补丁文件应用于哪些文件patch -p1
(即 的输出 git diff $sha1..$sha1^ -- $file
)?
它适用于工作目录中的所有文件吗?
但工作目录可能与提交目录不同$sha1
。那么,将$sha1^
和之间的差异应用$sha1
到工作目录是否有意义,它可能与 相同,也可能不同$sha1
?
谢谢。
答案1
git diff $sha1..$sha1^
生成一个恢复提交的补丁$sha1
(它列出了该提交与其父提交之间的差异)。如果$file
指定,它将将该补丁限制为$file
给定提交中所做的更改。
然后将该补丁提供给,这将删除(和)patch -p1
使用的假目录名称,并尝试将补丁应用到补丁中列出的任何文件 (git
a/
b/
IE,$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
它。)