假设一个补丁是从过去的某个提交中创建的,并且不再适用于HEAD。如何找到补丁适用于“git apply”的历史记录中的第一个或最后一个提交?也许使用git bisect?但是哪个命令会告诉我补丁是否适用?理想情况下,我想回到那个提交,应用补丁,然后重新基于或合并原始HEAD,并进行差异比较以创建新的补丁(如果没有冲突)。之后,我想回到原始的HEAD,以便可以继续进行更多的补丁。背景:有一些需要重新滚动的补丁...(是的,还有一些生态系统仍然在使用补丁...)
git diff
创建的,而不是git format-patch
,并且您在git log
中使用的默认页面 less
。
以下是从git diff <sha1> <sha2>
创建的补丁的示例:diff --git a/osx/.bash_profile b/osx/.bash_profile
index c7b41df..fb80367 100644
--- a/osx/.bash_profile
+++ b/osx/.bash_profile
@@ -3,6 +3,10 @@
# Setup PATH for Homebrew packages
export PATH=/usr/local/bin:$PATH
+# Setup Scala variables
+export SCALA_HOME=/usr/local/Frameworks/scala # Symlinked directory
+export PATH=$PATH:$SCALA_HOME/bin
+
# Initialize rbenv,
# https://github.com/sstephenson/rbenv#homebrew-on-mac-os-x
eval "$(rbenv init -)"
请看这行代码:
+export SCALA_HOME=/usr/local/Frameworks/scala # Symlinked directory
并在 git log --patch
或 git log -p
中搜索它。 在 less
中键入 /
,然后输入要搜索的正则表达式:
/\+export SCALA_HOME=/usr/local/Frameworks/scala # Symlinked directory
\+
进行转义,因为它在正则表达式中是一个特殊字符。按回车键可找到第一个匹配项,按n
可以找到下一个匹配项,或者按N
返回上一个匹配项。less
中使用空格键向下翻页,按b
向上翻页。git apply --3way
命令应该使用blob哈希值来定位每个文件的基本版本,并在一步中向前合并所有内容,假设它们存在于您的存储库历史记录中,并且您可以处理合并冲突。对于许多人来说,这可能是一个更简单的解决方案。
如果您仍然真的想知道一个包含差异所来自的基本文件的历史提交记录,我的脚本将扩展查找包含单个blob哈希的提交记录的其中一种解决方案,以尝试查找包含从补丁文件中提取的一组blob哈希的提交记录。
#!/bin/sh
# git-find-patch-base takes a patch produced by "git diff" and tries to locate commit(s)
# containing all source blobs
# The first parameter is the name of the patch file to examine
patch_file="$1"
# Any remaining parameters are passed as a group to the git log command using $@ below
shift
# Make a temporary file and capture a list of all the starting
# file blob hashes that the patch used in it. Note: Adding a file shows
# a starting hash of 00000000, so we filter that one out...
tmp_blob_file=$(mktemp)
echo "Examining patch file \"$patch_file\"..." 1>&2
grep -E "^index" "$patch_file" | colrm 1 6 | colrm 10 | sort | uniq | grep -v 00000000 > "$tmp_blob_file"
# Count how many unique blob hashes we identified
blobcount=$(cat "$tmp_blob_file" | wc -l)
echo "Found $blobcount unique blob hashes in patch..." 1>&2
# Use git log to get a list of commits to check against. Then, for
# each of those commits, count how many of the blob hashes that we
# wanted appear in it, and output the commit hash if it's at least the
# ideal blob count. Note: this is an imperfect searching method, since
# there is a chance for hash collision, exacerbated since the grep is not
# forcing the short hashes to only match the beginning of the long
# hashes.
echo "Searching log/tree history of git..." 1>&2
git log "$@" --pretty=format:'%T %h %s' \
| while read tree commit subject ; do
if test $(git ls-tree -r "$tree" | grep -f "$tmp_blob_file" | wc -l) -ge "$blobcount" ; then
echo "$commit" "$subject"
break
fi
done
# Clean up the temporary file we made...
rm "$tmp_blob_file"
git log
以帮助扩展/限制要检查的提交列表。如果您想要相对于特定分支的第一个提交,可以运行git-find-patch-base foo.patch branchname
。如果您完全不知道某个东西来自哪里,可以运行git-find-patch-base foo.patch --all
并在它完成时喝杯咖啡。git log有许多有用的限制器,例如--grep
或--author
,可以加快此过程。
所示的脚本在while循环中使用break
停止第一次匹配。您可以将其删除,这将彻底搜索所有候选提交。
git diff
或git format-patch
创建的补丁在哪里? - user456814git bisect
要求您传递一个“好的修订版”,在这种情况下,该修订版应用补丁而不产生冲突。由于这个原因,我怀疑git bisect
并不总是一个好工具。 - user456814git log -S <search-string>
或git log -G <regex>
来查找第一次添加/删除<search-string>
或<regex>
的行,对吧?这可能会帮助你找到可能的“第一个提交”,其中可能生成了补丁。 - user456814