【问题标题】:How to know if there is a git rebase in progress?如何知道是否正在进行 git rebase?
【发布时间】:2010-10-13 06:58:11
【问题描述】:

当我启动git rebase -i 时,我可以发出git rebase --continuegit rebase --abort 之类的命令。这些命令仅在 rebase 正在进行时才有效。

我如何知道是否正在进行变基?

(我将非常感谢有关 rebase 如何在内部工作的一些细节;git 对 repo 做了什么使其处于“rebase in progress”状态,?)

【问题讨论】:

    标签: git git-rebase


    【解决方案1】:

    2021 年更新:

    正如我在“git stash is slow on windows”中提到的,Git for Windows 2.19(2018 年 9 月)、git stash(和 git rebase)不再是纯脚本,而是实际上是用 git.exe 编译的二进制文件。

    Timanswer 说明了如何仍然难以确定变基是否正在进行。

    这在邮件列表中进行了讨论,导致补丁像“status: rebase and merge can be in progress at the same time”:

    自从引入了git rebase -r,这是可能的。
    但是我们的机器认为这是不可能的,并且在合并过程中没有说明正在进行的 rebase。

    在此之前(2016 年)有一个“rebase in progress”检测案例,带有“worktree.c: check whether branch is rebased in another worktree

    这个函数find_shared_symref()用在几个地方:

    1. in builtin/branch.c: 用于检测分支是否在别处签出并拒绝删除该分支。
    2. builtin/notes.c:它用于检测一个笔记是否被合并到另一个工作树中
    3. branch.c中,die_if_checked_out()函数实际上被“git checkout”和“git worktree add”用来查看分支是否已经在别处签出并拒绝操作。

    在情况 1 和 3 中,如果 rebase 正在进行,“HEAD”将处于分离模式
    find_shared_symref() 未能检测到它并声明“no branch is checked out here”,即不是我们想要的。


    原答案:2010

    一方面,there is a ORIG_HEAD 在变基期间到位(但不限于变基命令)

    但您也可以查看 2010 Git 1.7.0 git-rebase.sh script 本身(您可以了解它是“内部”;)。
    像这样的线条可以给你另一个线索:

    dotest="$GIT_DIR"/rebase-merge
    test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || die "No rebase in progress?"
    

    sabgentoncomments:

    • 文件夹rebase-apply 似乎与rebase 一起出现,
    • 但文件夹 rebase-merge 仅与 rebase -i 一起显示。

    还有hippycomments,在2017 年:

    编码指南不鼓励使用-o(参见Documentation/CodingGuidelines),因此now (2017, but also since 2011, Git 1.7.6)的正确方法是:

    (test -d ".git/rebase-merge" || test -d ".git/rebase-apply") || die "No rebase in progress?"
    

    Jelaby 建议in the comments

    (test -d "$(git rev-parse --git-path rebase-merge)" || \
     test -d "$(git rev-parse --git-path rebase-apply)" )
    

    这可以正确处理没有.git 目录的工作树和异常或非标准布局,还允许您从工作目录的子目录运行此测试。

    那是因为git rev-parse --git-path <path>: 确实解析了“$GIT_DIR/<path>”。

    Elizandro - SparcBR 加上in the comments

    还可以将错误重定向到 null:

    (test -d "$(git rev-parse --git-path rebase-merge)" || test -d "$(git rev-parse --git-path rebase-apply) 2>/dev/null"
    

    Git 2.6+(2015 年第三季度)将在 rebase 期间打印更多信息:

    参见commit 592e412commit 84e6fb9(2015 年 7 月 6 日)、commit 84e6fb9(2015 年 7 月 6 日)和commit df25e94commit 05eb563(2015 年 6 月 30 日)Guillaume Pagès (gitster)
    (由 Junio C Hamano -- gitster -- 合并于 commit 178d2c7,2015 年 8 月 3 日)

    status:在rebase -i期间提供更多信息

    git statusrebase -i 期间提供更多信息,关于在变基期间完成的命令列表。
    它显示:

    • 执行的最后两个命令和
    • 接下来要执行的两行。

    它还提供了在.git 目录中查找整个文件的提示。


    尝试检测 提示 不适用于 Git 2.26+,如 commit 6d04ce7

    所示

    git rebase”已经学会默认使用合并后端(即驱动“rebase -i”的机器),同时允许“--apply”选项使用“apply”后端(例如“format-patch piped to am”的道德等价物。
    rebase.backend配置变量可以设置自定义。)

    commit 10cdb9fcommit 2ac0d62commit 8295ed6commit 76340c8commit 980b482commit c2417d3commit 6d04ce7commit 52eb738commit 8af14f0commit befb89c、@989 @、commit 93122c9commit 55d2b6dcommit 8a997edcommit 7db00f0commit e98c426commit d48e5e2(2020 年 2 月 15 日)和commit a9ae8fdcommit 22a69fd(2020 年 1 月 16 日)@987654。 br>(由 Junio C Hamano -- gitster -- 合并于 commit 8c22bd9,2020 年 3 月 2 日)

    git-prompt:更改基于交互的变基的提示

    过去,我们对不同类型的变基有不同的提示:

    REBASE: for am-based rebases
    REBASE-m: for merge-based rebases
    REBASE-i: for interactive-based rebases
    

    尚不清楚为什么这种区分是必要的或有帮助的;当。。。的时候 在提交e752019 中添加了提示(“改进 bash 提示以检测 各种状态,例如未完成的合并”,2007-09-30,Git v1.5.5-rc0),它只是添加了这三种不同的类型。
    也许当时有一个有用的目的,但已经发生了一些变化:

    • 合并后端在交互式后端上实施后被删除,导致基于合并的变基的提示从 REBASE-m 更改为 REBASE-i
    • 交互式后端用于多种不同类型的非交互式变基,因此提示中的“-i”部分并不真正代表它过去的含义。
    • Rebase 后端获得了更多功能,并且有大量重叠,有时很难区分它们。
    • 后端之间的行为差​​异也已解决。
    • 我们希望将默认后端从 am 更改为 interactive,这意味着如果我们不更改提示,并且仅当他们指定 --am--whitespace 或 @ 时,默认情况下人们会得到“REBASE-i” 987654432@ 他们会收到“REBASE”提示吗?
    • 未来,我们计划让“--whitespace”、“-C”甚至“--am”运行交互式后端,只要它能够处理am-backend 可以处理的所有事情。

    出于所有这些原因,将任何类型的变基的提示设为“REBASE”。


    Since Git 2.17 (March 2018),你还有:

    git rebase --show-current-patch
    

    它在交互式 rebase 期间显示 .git/REBASE_HEAD 的内容,可以在冲突期间暂停。

    【讨论】:

    • git-status 不应该告诉你这个吗?
    • 从 git 版本 1.7.3.1 开始,git status 没有说明变基状态。
    • 但是,EasyGiteg status does tell you
    • 解释此答案中的git-rebase.sh 代码,如果在回购根目录的.git 文件夹内,目录rebase-merge 或@ 中的一个,Git 知道正在进行rebase 987654445@ 存在。
    • 在 Git 2.7 甚至更早的版本中,您可以使用 (test -d "$(git rev-parse --git-path rebase-merge)" || test -d "$(git rev-parse --git-path rebase-apply)" 之类的东西。这可以正确处理没有 .git 目录的工作树和异常或非标准布局,并且还允许您从工作目录的子目录运行此测试。
    【解决方案2】:

    您还可以在__git_ps1 function in contrib/completion/git-prompt.sh 中查看此类检测是如何完成的,可用于 git-aware bash prompt:

                    if [ -f "$g/rebase-merge/interactive" ]; then
                            r="|REBASE-i"
                            b="$(cat "$g/rebase-merge/head-name")"
                    elif [ -d "$g/rebase-merge" ]; then
                            r="|REBASE-m"
                            b="$(cat "$g/rebase-merge/head-name")"
                    else
                            if [ -d "$g/rebase-apply" ]; then
                                    if [ -f "$g/rebase-apply/rebasing" ]; then
                                            r="|REBASE"
                                    elif [ -f "$g/rebase-apply/applying" ]; then
                                            r="|AM"
                                    else
                                            r="|AM/REBASE"
                                    fi
                            fi
                    fi
    

    【讨论】:

      【解决方案3】:

      如果正在进行交互式变基,这将告诉你你在这个过程中的位置:

      $ cat .git/rebase-merge/done 
      pick 786139e lrg
      edit 668b8a6 ktio
      $ 
      

      现在我正在交互式 rebase 中编辑“ktio”补丁。

      如果没有变基,它将如下所示:

      $ cat .git/rebase-merge/done 
      cat: .git/rebase-merge/done: No such file or directory
      $ 
      

      【讨论】:

        【解决方案4】:

        从 bash 命令行:

        ls `git rev-parse --git-dir` | grep rebase
        

        如果存在变基文件夹,则返回退出代码 0(成功),并将变基文件夹输出到 STDOUT。如果你 not 在 rebase 的中间,那么它将不输出任何内容并返回非 0 退出代码。所以你甚至可以做这样的事情:

        ls `git rev-parse --git-dir` | grep rebase || echo no rebase
        

        【讨论】:

          【解决方案5】:

          如果你有EasyGiteg status 会告诉你:

          $ eg status
          (Not currently on any branch.)
          (YOU ARE IN THE MIDDLE OF A INTERACTIVE REBASE; RUN 'eg help topic middle-of-rebase' FOR MORE INFO.)
          Changes ready to be committed ("staged"):
              modified:   .gitmodules
              renamed:    config_loader.rb -> code/config_loader.rb
          Newly created unknown files:
              vendor/
          (YOU ARE IN THE MIDDLE OF A INTERACTIVE REBASE; RUN 'eg help topic middle-of-rebase' FOR MORE INFO.)
          

          在彩色终端中,通知非常显眼:

          eg help topic middle-of-rebase 显示文档“How to resolve or abort an incomplete rebase”。)

          【讨论】:

            【解决方案6】:

            这里有一些不好的答案。 git 并没有真正说明它应该如何工作,所以唯一的答案是“git 是如何做到的?”。代码是here

            int wt_status_check_rebase(const struct worktree *wt,
                           struct wt_status_state *state)
            {
                struct stat st;
            
                if (!stat(worktree_git_path(wt, "rebase-apply"), &st)) {
                    if (!stat(worktree_git_path(wt, "rebase-apply/applying"), &st)) {
                        state->am_in_progress = 1;
                        if (!stat(worktree_git_path(wt, "rebase-apply/patch"), &st) && !st.st_size)
                            state->am_empty_patch = 1;
                    } else {
                        state->rebase_in_progress = 1;
                        state->branch = get_branch(wt, "rebase-apply/head-name");
                        state->onto = get_branch(wt, "rebase-apply/onto");
                    }
                } else if (!stat(worktree_git_path(wt, "rebase-merge"), &st)) {
                    if (!stat(worktree_git_path(wt, "rebase-merge/interactive"), &st))
                        state->rebase_interactive_in_progress = 1;
                    else
                        state->rebase_in_progress = 1;
                    state->branch = get_branch(wt, "rebase-merge/head-name");
                    state->onto = get_branch(wt, "rebase-merge/onto");
                } else
                    return 0;
                return 1;
            }
            

            它主要检查这几个文件/目录是否存在(注意!stat() 表示“文件是否存在”)。 amgit am,用于从邮箱应用补丁,我怀疑除了 Linux 开发人员之外的任何人都在使用。

            • rebase_in_progress: .git/rebase-apply && !.git/rebase-apply/applying || .git/rebase-merge && !.git/rebase-merge/interactive
            • interactive_rebase_in_progress: .git/rebase-merge && .git/rebase-merge/interactive
            • am_in_progress: .git/rebase-apply && .git/rebase-apply/applying

            我想如果你想知道是否有任何类型的变基/am 正在发生,只需检查 .git/rebase-apply.git/rebase-merge 是否存在。

            【讨论】:

            • 好点。赞成。我在编辑/修订的答案中引用了您的答案。
            • 如果.git是一个带有实际git文件夹路径的文件,应该如何修改?
            • 如果您在工作树中并且.git 是一个文件,那么您需要解析该文件(例如,它可能包含gitdir: /path/to/repo/.git/worktrees/worktreename)然后检查/path/to/repo/.git/worktrees/worktreename/rebase-apply 等。
            【解决方案7】:

            我没看清楚,所以在这里:

            在变基过程中,如果有一个正在进行中,git status 现在就足够了,因为它提供了信息(作为参考,我领导了名为 masterrbBr 的小分支):

            interactive rebase in progress; onto 5f8e534
            Last command done (1 command done):
               pick 1b7a450 BRANCH: another comment
            No commands remaining.
            You are currently rebasing branch 'rbBr' on '5f8e534'.
              (fix conflicts and then run "git rebase --continue")
              (use "git rebase --skip" to skip this patch)
              (use "git rebase --abort" to check out the original branch)
            
            Unmerged paths:
              (use "git restore --staged <file>..." to unstage)
              (use "git add <file>..." to mark resolution)
                    both modified:   User.java
            
            no changes added to commit (use "git add" and/or "git commit -a")
            

            这在解决冲突之前显示,在解决冲突之后显示:

            interactive rebase in progress; onto 5f8e534
            Last command done (1 command done):
               pick 1b7a450 BRANCH: another comment
            No commands remaining.
            You are currently rebasing branch 'rbBr' on '5f8e534'.
              (all conflicts fixed: run "git rebase --continue")
            
            Changes to be committed:
              (use "git restore --staged <file>..." to unstage)
                    modified:   User.java
            
            PS C:\my_git_repos\learning_git> git rebase --continue                                                                                                                                                                                       [detached HEAD 9645135] BRANCH: another comment
             1 file changed, 1 insertion(+)
            Successfully rebased and updated refs/heads/rbBr.
            

            【讨论】:

            • 正确,但不适用于脚本:解析/grepping git status 输出不是一个好习惯,正如 stackoverflow.com/questions/3921409/… 中所述
            • 好一个。只需添加--porcelain--porcelain=v2 即可使其更适合自动化脚本。
            【解决方案8】:

            我正在使用这个命令is_rebase=$(git status | grep "rebasing" | wc -l)

            【讨论】:

            • 这被破坏了:如果你有一个包含“变基”的脏文件,它会打印出你正在变基,即使你不是。
            猜你喜欢
            • 2012-07-17
            • 1970-01-01
            • 2013-09-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多