6

假设补丁是从过去的特定提交中创建的,并且不再适用于 HEAD。

我怎样才能找到 HEAD 历史上的第一个或更好的最后一个提交,这个补丁适用于 "git apply" ?也许有 git bisect 的东西?但是哪个命令会告诉我补丁是否适用?

理想情况下,我想回到那个提交,应用补丁,然后基于原始 HEAD 或与原始 HEAD 合并,然后再次 diff 以创建新补丁,除非存在冲突。在此之后,我想回到原来的 HEAD,所以我可以继续做更多的补丁。

背景:有许多补丁需要重新发布......(是的,有些生态系统仍然存在补丁......)

4

2 回答 2

2

这个答案假设补丁是用创建的git diff,而不是创建的,git format-patch并且你的默认寻呼机git logless

这是一个从创建的补丁示例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 --patchor中搜索git log -p。输入/when in less,然后输入要搜索的正则表达式:

/\+export SCALA_HOME=/usr/local/Frameworks/scala # Symlinked directory

The在这里+被转义\,因为它是正则表达式中的特殊字符。按回车键查找第一个匹配项,然后n调出下一个匹配项,或N转到上一个匹配项。

这将帮助您找到可能是补丁来源的候选提交。您还可以使用空格键less向下翻页和b向上翻页。

于 2014-05-28T06:07:33.160 回答
1

git 希望你这样做的方式

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可以加快这个过程。

如图所示的脚本在第一个匹配时停止,并且break退出了 while 循环。你可以删除它,它会一直搜索到所有候选提交。

于 2018-06-21T20:10:14.297 回答