【问题标题】:Why does git-bisect have to be run from the top level directory of the working tree?为什么 git-bisect 必须从工作树的顶级目录运行?
【发布时间】:2012-09-10 21:04:52
【问题描述】:

如果有人试图从存储库根目录以外的任何地方运行任何 git-bisect 命令,则会被告知:

您需要从工作树的顶层运行此命令。

这是为什么呢?我知道没有其他 git 命令有这个要求,而且我看不出 bisect 应该是特殊的明显原因。手册页也没有提到这个限制。

这真的没什么大不了的。我主要是好奇。

【问题讨论】:

  • 我认为这是为了明确您的整个工作副本将在对分期间进行修改
  • 并且为了避免如果你在一个被删除的目录中该怎么做的边缘情况。再说一遍,git 不跟踪目录...
  • @CharlesB,Arafangion,这两点同样适用于 git-checkout 和 git-bisect,不是吗?
  • @Arafangion 任何改变 wc 的命令都是正确的——拉取、合并、变基、结帐等。 bisect 没什么特别的。我认为这只是另一个误解。

标签: git git-bisect


【解决方案1】:

查看项目中的一些提交,我看到 Marcel M. Cary (marcel@oak.homeunix.org) 的一个提交

他在提交中说(它恰好是关于 git-pull 但我认为它是相关的)

"git pull" 失败,因为 POSIX shell 有当前工作的概念 与 getcwd() 不同的目录。 shell 存储这个路径 在残疾人。因此,“cd ../”在 shell 脚本,而不是 C 程序中的 chdir("../")。外壳解释 "../" 通过从本质上剥离最后一个文本路径组件 PWD,而 C chdir() 遵循当前目录中的“..”链接 在文件系统上。当 PWD 是符号链接时,这些是不同的 目的地。结果,Git 的 C 命令找到了正确的 顶级工作树,而 shell 脚本则没有。

https://github.com/git/git/commit/08fc0608657ee91bc85276667804c36a93138c7d

所以我想说部分原因是因为 git-bisect 是一个 shell 脚本,不能相信它可以自行找到顶层(当涉及符号链接时)。

【讨论】:

  • 我希望有更好的理由,但这不是你的错。非常感谢您做一些研究。
  • 是的,有点令人失望。继续深入研究代码;它的评论非常好(有时还很幽默),提交信息也很棒。
【解决方案2】:

二分过程需要检查项目的不同版本。如果特定修订不包含当前文件夹,则当前文件夹将被删除。

在这种情况下,您的 shell 最终可能位于不再位于文件系统上的文件夹中!然后,Git 将无法找到顶层的 .git 文件夹,因此如果没有干预,对分过程将无法继续。

演示:

$ git rev-parse --show-toplevel
/path/to/project
$ mkdir tmp
$ cd tmp
$ rmdir ../tmp
$ git rev-parse --show-toplevel
fatal: Unable to read current working directory: No such file or directory

当然,在git checkout 时也会出现同样的问题,事后也可以轻松解决,例如使用cd ..(willoller 解释了为什么它在 shell 中有效,但在 git 中无效)。

但由于二等分是一个过程,因此在开始之前避免这种情况是有意义的,特别是如果我们想使用自动化,例如git bisect run

【讨论】:

    【解决方案3】:

    因此,Git 的 C 命令会找到正确的顶级工作树,而 shell 脚本却找不到。

    嗯,随着 Git 2.21(2019 年 2 月),git bisect 继续从 shell 脚本过渡到 C。

    请参阅commit 06f5608commit 450ebb7commit 129a6cfcommit 4fbdbd5commit e3b1e3bcommit 0f30233commit 5e82c3d(2019 年 1 月 2 日)Pranit Bauva (pranitbauva1997)
    帮助者:Ramsay Jones (jeffhostetler)Stephan Beyer (sbeyer)
    (由 Junio C Hamano -- gitster --commit 09a9c1f 中合并,2019 年 2 月 7 日)

    bisect--helper: bisect_start shell 函数部分在 C 中

    在 C 中部分地重新实现 bisect_start shell 函数并添加 bisect-start 子命令到 git bisect--helper 来调用它 git-bisect.sh .

    这还没有完成,但迁移的副作用是能够从子文件夹执行git bisect


    Git 2.23 进一步改进了向 C 的转换。
    请参阅 Johannes Schindelin (dscho)commit 7877ac3(2019 年 5 月 21 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 5b476dc,2019 年 6 月 17 日)


    使用 Git 2.25(2020 年第一季度),bisect_reset 受益于修复。

    Tanushree Tumane (tanushree27)commit 51a0a4e(2019 年 12 月 9 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 4bfc9cc,2019 年 12 月 25 日)

    bisect--helper: 避免使用后释放

    指导人:Johannes Schindelin
    指导人:Christian Couder
    签字人:Tanushree Tumane
    签字人:Miriam Rubio

    5e82c3dd22a(“bisect--helper:bisect_resetC 中的 shell 函数”,2019-01-02,Git v2.21.0-rc0 -- merge)中,[git bisect](https://git-scm.com/docs/git-bisect) reset子命令已移植到 C。
    当调用git checkout 失败时,向用户报告错误消息(could not check out original HEAD)。

    但是,此错误消息使用了刚刚发布的strbuf
    让我们切换一下:先使用它,然后释放它。


    从 Git 2.26(2020 年第一季度)开始,“git bisect--helper”的底层机制被重构为更易于重用的部分。

    参见commit 6c69f22commit 9ec598ecommit 45b6370commit cdd4dc2commit e8e3ce6commit ce58b5dcommit 7613ec5(2020 年 2 月 17 日)Pranit Bauva (pranitbauva1997)
    请参阅commit 680e8a0commit b8e3b2fcommit 16538bf(2020 年 2 月 17 日)Miriam Rubio (``)
    参见commit bfacfcecommit 292731c(2020 年 2 月 17 日)Tanushree Tumane (tanushree27)
    (由 Junio C Hamano -- gitster -- 合并于 commit 25063e2,2020 年 3 月 5 日)

    例如:

    bisect--helper:引入新的decide_next()功能

    指导人:Christian Couder
    签字人:Tanushree Tumane
    签字人:Miriam Rubio支持>

    让我们将代码从 bisect_next_check() 重构为一个新的 decide_next() 辅助函数。

    这删除了一些goto 语句,使代码更简单、更清晰、更易于理解。


    在 Git 2.28(2020 年第三季度)之前,解析“git bisect start”命令行的代码在验证参数时很松懈。

    参见Carlo Marcelo Arenas Belón (carenas)commit 4d9005f(2020 年 5 月 20 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 63e50b8,2020 年 6 月 9 日)

    bisect--helper:避免在start --term-* 中出现语法错误的段错误

    签字人:Carlo Marcelo Arenas Belón
    签字人:Christian Couder

    06f5608c14 ("bisect--helper: bisect_start shell function partial in C", 2019-01-02, Git v2.21.0-rc0 -- merge) 为[git bisect 添加了一个松散的解析器start](https://git-scm.com/docs/git-bisect) 这可能会在错误的语法调用下导致以自定义术语开头的段错误。

    检测命令行中是否有足够的参数可用于--term-{old,good,new,bad},如果没有,则以原始实现将显示的相同语法错误中止。


    在 Git 2.29(2020 年第四季度)之前,“git bisect start X Y(man),当 X 和 Y 不是有效的提交对象名称时,应该将 X 和 Y 作为路径规范,但没有t.

    参见Christian Couder (chriscool)commit 73c6de0(2020 年 9 月 25 日)。
    (由 Junio C Hamano -- gitster -- 合并到 commit 03a0182,2020 年 10 月 4 日)

    bisect: 启动时不要使用无效的oid作为rev

    签字人:Christian Couder
    签字人:Johannes Schindelin

    06f5608c14 ("bisect--helper: bisect_start shell function partial in C", 2019-01-02, Git v2.21.0-rc0 -- merge) 中,我们更改了以下 shell 代码:

    -      rev=$(git rev-parse -q --verify "$arg^{commit}") || {
    -              test $has_double_dash -eq 1 &&
    -              die "$(eval_gettext "'\$arg' does not appear to be a valid revision")"
    -              break
    -      }
    -      revs="$revs $rev"
    

    进入:

    +      char *commit_id = xstrfmt("%s^{commit}", arg);
    +      if (get_oid(commit_id, &oid) && has_double_dash)
    +              die(_("'%s' does not appear to be a valid "
    +                    "revision"), arg);
    +
    +      string_list_append(&revs, oid_to_hex(&oid));
    +      free(commit_id);
    

    如果"has_double_dash" 为假时“arg”无效,旧代码将“中断”出参数循环。

    不过,在新的 C 代码中,oid_to_hex(&oid) 被无条件地附加到“revs”。这首先是错误的,因为“oid”是垃圾,因为 get_oid(commit_id, &oid) 失败,其次是因为它没有跳出参数循环。

    不跳出参数循环意味着“arg”不被视为路径限制(这是错误的)。


    在 Git 2.29(2020 年第四季度)中,继续用 C 重写“git bisect(man) 脚本。

    commit 517ecb3commit 09535f0(2020 年 9 月 24 日)Pranit Bauva (pranitbauva1997)
    请参阅commit c7a7f48(2020 年 9 月 24 日)和 commit 7b4de74commit 3027676commit ef5aef5(2020 年 8 月 28 日)Miriam Rubio (mirucam)
    (由 Junio C Hamano -- gitster -- 合并到 commit f4cc68c, 04 2020 年 10 月)

    bisect--helper:在 C 中重新实现 bisect_nextbisect_auto_next shell 函数

    指导者:Lars Schneider
    指导者:Christian Couder
    指导者:Johannes Schindelin
    签字人:Pranit Bauva
    签字人:Tanushree Tumane
    签字人:Miriam Rubio支持>

    在 C 中重新实现 bisect_next()bisect_auto_next() shell 函数,并将子命令添加到 [git](https://github.com/git/git/blob/517ecb3161daa4503f7638489fd44177b3659913/Documentation/git-.txt)<sup>([man](https://git-scm.com/docs/git-))</sup> bisect--helper 以从 git-bisect.sh 调用它们。

    bisect_auto_next() 函数返回一个枚举 bisect_error 类型作为整体 [git bisect](https://github.com/git/git/blob/517ecb3161daa4503f7638489fd44177b3659913/Documentation/git-bisect.txt)<sup>([man](https://git-scm.com/docs/git-bisect))</sup> 可以在 bisect_next() 退出时返回错误代码。

    bisect_next() 失败时返回错误,修复 shell 脚本版本的错误。

    使用--bisect-next--bisect-auto-next 子命令是将shell 函数移植到C 以使用现有测试套件的临时措施。随着更多功能的移植,--bisect-auto-next 子命令将被淘汰,将被其他一些方法调用。


    在 Git 2.30(2021 年第一季度)中,继续用 C 重写“git bisect(man)

    参见commit b0f6494commit 5c517fecommit 9b437b0commit 27257bccommit 04774b4commit e439607commit 88ad372(2020 年 10 月 15 日)Pranit Bauva (pranitbauva1997)
    (合并Junio C Hamano -- gitster --commit cfdc70b,2020 年 11 月 9 日)

    bisect--helper:在 C 中重新实现 bisect_state & bisect_head shell 函数

    指导者:Lars Schneider
    指导者:Christian Couder
    指导者:Johannes Schindelin
    签字人:Pranit Bauva
    签字人:Tanushree Tumane
    签字人:Miriam Rubio sup>
    审核人:Johannes Schindelin

    在 C 中重新实现 bisect_state() shell 函数,并将子命令 --bisect-state 添加到 git-bisect--helper 以从 git-bisect.sh 调用它们。


    使用 Git 2.31(2021 年第一季度):继续用 C 语言重写“git bisect(man)

    参见commit 97b8294commit e4c7b33commit 9feea34commit b7a6f16commit 68efed8commit 2b1fd94commit 97d5ba6(2021 年 2 月 3 日)Pranit Bauva (pranitbauva1997)
    (合并Junio C Hamano -- gitster --commit 0871fb9,2021 年 2 月 17 日)

    bisect--helper:退休--bisect-write子命令

    指导者:Lars Schneider
    指导者:Christian Couder
    指导者:Johannes Schindelin
    签字人:Pranit Bauva
    签字人:Tanushree Tumane
    签字人:Miriam Rubio支持>

    git-bisect.sh shell 脚本中不再使用--bisect-write 子命令。
    而是直接从 C 实现中调用函数 bisect_write()


    "git bisect"(man) 在 2.30 的时间范围内用 C 重新实现了更多,并没有将带注释的标签作为好/坏的端点。
    此回归已在 Git 2.31.1(2021 年第一季度)中得到纠正。

    参见Jeff King (peff)commit 7730f85(2021 年 3 月 16 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 35381b1,2021 年 3 月 19 日)

    bisect:将注释标签剥离到提交

    签字人:杰夫·金

    此补丁修复了一个错误,即 'git-bisect'(man) 无法将带注释的标签接收为“git bisect”好<tag> 等。
    这是27257bc 中的回归(“bisect--helper:在 C 中重新实现 bisect_state & bisect_head shell 函数”,2020-10-15,Git v2.30.0-rc0 -- mergebatch #4 中列出) .

    原来的shell代码叫:

    sha=$(git rev-parse --verify "$rev^{commit}") ||
            die "$(eval_gettext "Bad rev input: \$rev")"
    

    这会将输入剥离到提交(如果不可能,则抱怨)。
    但是 C 代码只是调用了get_oid(),这将产生标签的 oid。

    解决方法是剥离到提交。
    这里的错误信息对于 Git 来说有点不习惯(因为它以大写字母开头)。

    新的错误信息:

    Bad rev input (not a commit): xxxx
    

    警告:“git bisect skip(man) 当自定义词用于新/旧时 not 在 Git 2.31 中是否有效,已通过以下方式更正Git 2.32(2021 年第二季度)。

    参见 Ramsay Jones (ramsay-jones)commit 4cd66e7(2021 年 4 月 29 日)。
    (由 Junio C Hamano -- gitster -- 合并到 commit 8ca4771,2021 年 5 月 11 日)

    bisect--helper:在“bisect skip”命令中使用BISECT_TERMS

    报告人:Trygve Aaberge
    签字人:Bagas Sanjaya
    签字人:Ramsay Jones支持>

    Commit e4c7b33 ("bisect--helper: reimplement bisect_skip shell function in C", 2021-02-03, Git v2.31.0-rc0 -- mergebatch #9 中列出),作为shell 到 C 的转换,在新的“bisect skip”命令执行期间忘记读取“条款”文件 (.git/BISECT_TERMS)。
    因此,“bisect skip”命令将使用默认的“坏”/“好”术语。
    如果二等分项已设置为非默认值(例如通过“bisect start”命令),则“bisect skip”命令将失败。

    为了纠正这个问题,我们在“bisect--helper”的“--bisect-skip”命令实现中插入了对get_terms() 函数的调用,该函数从该文件中读取非默认条款(如果已设置) '。

    另外,添加test 以防止未来可能出现的回归。


    在 Git 2.33(2021 年第三季度)中,“git bisect(man) 催生了 git show-branch(man) 只是为了漂亮地打印签出要测试的下一个版本后提交的标题;这已用 C 重写。

    参见commit 1fcc40c(2021 年 7 月 28 日)和 commit ffcb4e9(2021 年 7 月 27 日)Junio C Hamano (gitster)
    (由 Junio C Hamano -- gitster -- 合并于 commit ae2d05d,2021 年 8 月 24 日)支持>

    bisect: 不要仅仅为了显示当前提交而运行 show-branch

    在“git bisect(man) 的脚本版本中,我们使用“git show-branch(man) 来描述单个提交bisect 日志,并在签出下一个要测试的版本后发送给交互式用户。

    当写入平分日志条目的辅助函数在0f30233 处重写时,“git show-branch”的先前用法丢失了(“bisect--helper:bisect_write C 中的 shell 函数”,2019-01-02, Git v2.21.0-rc0 -- merge) 在 C 中

    但是从0871984 (bisect: make , 2009-05-09, Git v1.6.4-rc0 -- merge) (bisect: make "git bisect" 使用新的--next-all bisect-helper 函数,2009-05-09) 开始使用在ef24c7c (bisect--helper: add , 2009-04-19, Git v1.6.4-rc0 -- @987654461 引入的忠实 C-rewrite @) (bisect--helper: 添加“--next-exit”输出二分结果,2009-04-19)。

    使用我们的助手 pretty.c::format_commit_message() 显示“[<full hex>] <subject>”非常简单,而生成 show-branch 则有点过头了。
    让我们失去一个外部进程。

    【讨论】:

    • 您不断为较新的 Git 版本更新此答案的奉献精神令人印象深刻!
    • @ParkerCoates 谢谢。用 C 重写是一项跨越多个 Git 版本的工作。 (我没有贡献,我只是在这里报告它)
    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 1970-01-01
    • 2021-10-14
    • 2017-12-19
    • 1970-01-01
    • 2015-12-07
    相关资源
    最近更新 更多