我的历史记录如下:
* 3830e61 Add data escaping. (Bad)
* 0f5e148 Improve function for getting page template.
* aaf8dc5 Merge branch 'navigation'
|\
| * 3e667f8 Add icons.
| * 43a07b1 Add menu styles. (Breaks)
| * 107ca95 Add Responsive Nav. (Good)
* | ea3d736 Add ‘Admin’ notice.
* | 17ca0bb Update placeholder text.
|/
* f52cc34 Add featured image.
* 2abd954 Style placeholders.
我正在尝试了解更多内容并git bisect
,但我对此历史遇到了麻烦。我知道107ca95
很好,3830e61
很糟糕。当我运行git bisect
时,将忽略提交107ca95..3e667f8
。我碰巧知道43a07b1
是引入回归的提交,但它永远不会被评估。
这大致是我所做的:
git checkout master
git bisect start
git bisect bad
git bisect good 107ca95
git bisect bad (multiple times)
无论我做什么,都不会检查107ca95..3e667f8
进行测试。
在bisect中测试这些提交有什么方法可以基本上“平整”历史记录吗?我知道我可以使用互动rebase
来平息历史,但我不想这样做。
答案 0 :(得分:11)
这是一个非常古老但没有答案的问题。我决定进行调查,发现我可以证明Git的行为与问题所说的不同。 一个解释是Git改进了bisect 的算法,或者提问者在标记提交时犯了错误。
我正在努力学习更多和git bisect,但我对这段历史遇到了麻烦。我知道
107ca95
很好,3830e61
很糟糕。当我运行git bisect时,将忽略提交107ca95..3e667f8
。我碰巧知道43a07b1
是引入回归的提交,但永远不会评估。
我写了一些代码来检查它是否被评估。我的测试显示它已被评估。运行以下代码并验证是否显示带有消息Add menu styles.
的提交。
进一步评论:
107ca95..3e667f8
被忽略”:请注意,您标记为“好”的提交将不会被评估,因为git已经知道它是好的。
# bad: [d7761d6f146eaca1d886f793ced4315539326866] Add data escaping. (Bad)
# good: [f555d9063a25a20a6ec7c3b0c0504ffe0a997e98] Add Responsive Nav. (Good)
git bisect start 'd7761d6f146eaca1d886f793ced4315539326866' 'f555d9063a25a20a6ec7c3b0c0504ffe0a997e98'
# good: [1b3b7f4952732fec0c68a37d5f313d6f4219e4ae] Add ‘Admin’ notice. (Good)
git bisect good 1b3b7f4952732fec0c68a37d5f313d6f4219e4ae
# bad: [f9a65fe9e6cde4358e5b8ef7569332abfb07675e] Add icons. (Bad)
git bisect bad f9a65fe9e6cde4358e5b8ef7569332abfb07675e
# bad: [165b8a6e5137c40ce8b90911e59d7ec8eec30f46] Add menu styles. (Bad)
git bisect bad 165b8a6e5137c40ce8b90911e59d7ec8eec30f46
# first bad commit: [165b8a6e5137c40ce8b90911e59d7ec8eec30f46] Add menu styles. (Bad)
使用Git 2.11.0在 Python 3 中运行。
要运行的命令:python3 script.py
""" The following code creates a git repository in '/tmp/git-repo' and populates
it with the following commit graph. Each commit has a test.sh which can be used
as input to a git-bisect-run.
The code then tries to find the breaking change automatically.
And prints out the git bisect log.
Written in response to http://stackoverflow.com/questions/17267816/git-bisect-with-merged-commits
to test the claim that '107ca95..3e667f8 are never checked out'.
Needs Python 3!
"""
from itertools import chain
import os.path
import os
import sh
repo = {
0x3830e61: {'message': "Add data escaping.", 'parents': [ 0x0f5e148 ], 'test': False} , # Last: (Bad)
0x0f5e148: {'message': "Improve function for getting page template.", 'parents': [ 0xaaf8dc5], 'test': False},
0xaaf8dc5: {'message': "Merge branch 'navigation'", 'parents': [ 0x3e667f8, 0xea3d736], 'test': False},
0x3e667f8: {'message': "Add icons.", 'parents': [ 0x43a07b1], 'test': False},
0x43a07b1: {'message': "Add menu styles.", 'parents': [ 0x107ca95], 'test': False} , # First: (Breaks)
0x107ca95: {'message': "Add Responsive Nav.", 'parents': [ 0xf52cc34], 'test': True}, # First: (Good)
0xea3d736: {'message': "Add ‘Admin’ notice.", 'parents': [ 0x17ca0bb], 'test': True},
0x17ca0bb: {'message': "Update placeholder text.", 'parents': [ 0xf52cc34], 'test': True},
0xf52cc34: {'message': "Add featured image.", 'parents': [ 0x2abd954], 'test': True},
0x2abd954: {'message': "Style placeholders.", 'parents': [], 'test': True},
}
bad = 0x3830e61
good = 0x107ca95
def generate_queue(_dag, parents):
for prev in parents:
yield prev
yield from generate_queue(_dag, _dag[prev]['parents'])
def make_queue(_dag, inits):
""" Converts repo (a DAG) into a queue """
q = list(generate_queue(_dag, inits))
q.reverse()
seen = set()
r = [x for x in q if not (x in seen or seen.add(x))]
return r
if __name__ == '__main__':
pwd = '/tmp/git-repo'
sh.rm('-r', pwd)
sh.mkdir('-p', pwd)
g = sh.git.bake(_cwd=pwd)
g.init()
parents = set(chain.from_iterable((repo[c]['parents'] for c in repo)))
commits = set(repo)
inits = list(commits - parents)
queue = make_queue(repo, inits)
assert len(queue) == len(repo), "queue {} vs repo {}".format(len(queue), len(repo))
commit_ids = {}
# Create commits
for c in queue:
# Set up repo
parents = repo[c]['parents']
if len(parents) > 0:
g.checkout(commit_ids[parents[0]])
if len(parents) > 1:
if len(parents) > 2: raise NotImplementedError('Octopus merges not support yet.')
g.merge('--no-commit', '-s', 'ours', commit_ids[parents[1]]) # just force to use 'ours' strategy.
# Make changes
with open(os.path.join(pwd, 'test.sh'), 'w') as f:
f.write('exit {:d}\n'.format(0 if repo[c]['test'] else 1))
os.chmod(os.path.join(pwd, 'test.sh'), 0o0755)
with open(os.path.join(pwd, 'message'), 'w') as f:
f.write(repo[c]['message'])
g.add('test.sh', 'message')
g.commit('-m', '{msg} ({test})'.format(msg=repo[c]['message'], test='Good' if repo[c]['test'] else 'Bad'))
commit_ids[c] = g('rev-parse', 'HEAD').strip()
# Run git-bisect
g.bisect('start', commit_ids[bad], commit_ids[good])
g.bisect('run', './test.sh')
print(g.bisect('log'))
答案 1 :(得分:10)
基本思路 - 要找到功能分支中的哪个提交会破坏您的主人,您必须在ea3d736 - 相关主HEAD之上重新应用它。
以下是测试脚本的示例(来自git doc),它为您执行此操作:
$ cat ~/test.sh
#!/bin/sh
# tweak the working tree by merging the hot-fix branch
# and then attempt a build
if git merge --no-commit ea3d736 &&
make
then
# run project specific test and report its status
~/check_test_case.sh
status=$?
else
# tell the caller this is untestable
status=125
fi
# undo the tweak to allow clean flipping to the next commit
git reset --hard
# return control
exit $status
运行它:
git bisect start 3830e61 f52cc34
git bisect good ea3d736 17ca0bb #If you want to test feature branch only
git bisect run ~/test.sh
答案 2 :(得分:0)
警告:关于“ git bisect
”的Automatically bisect with temporary modifications部分已使用Git 2.25(2020年第一季度)进行了更新。
它涉及以下步骤:在相关的master
提交(在OP的情况下为ea3d736
)的基础上重新应用要测试的提交
如果您不想移动git merge --no-commit
,则“ --no-ff
”需要“ HEAD
”。手册页中的“ git bisect
”已对它进行了纠正。 / p>
请参见commit 8dd327b的Mihail Atanassov (matana
)(2019年10月28日)。
(由Junio C Hamano -- gitster
--在commit fac9ab1中合并,2019年12月1日)
Documentation/git-bisect.txt
:添加--no-ff以合并命令签名人:Mihail Atanassov
评论人:乔纳森·尼德在对等操作期间,
hotfix
应用程序示例使用git merge --no-commit
将临时更改应用于工作树。在某些情况下,这可能是一个快进操作,
merge
将应用修补程序分支的提交,而不考虑--no-commit
(如git merge
manual中所述)。在病理情况下,这将在第一个等分步骤和快速转发的合并后
[
之间无限期地产生](https://git-scm.com/docs/git-bisect) run
git bisectHEAD
调用循环。在合并命令中添加
--no-ff
,以避免出现此问题。
git merge
确实提到:
请注意,快进更新不会创建合并提交,因此无法通过
--no-commit
停止这些合并。因此,如果要确保您的分支不会被
merge
命令更改或更新,请使用--no-ff
和--no-commit
。
答案 3 :(得分:-5)
您可以使用“git start”命令选择提交范围。该命令的概要是:
git bisect start <bad> <good>
在您的具体情况下,我认为正确的命令是:
git bisect start 3830e61 107ca95