如果 index.lock 存在,有没有办法让 git 自动重试命令?

Is there a way to make git automatically retry commands if index.lock exists?

我使用 Xcode 的一些源代码控制功能,特别是主编辑器中的 blame 功能,但在命令行上使用 git 进行我所有的实际版本控制。这意味着,命令行上的 git 命令经常失败并显示以下消息:

fatal: Unable to create '/path/to/repo/.git/index.lock': File exists.

Xcode 正在创建此文件以在它运行自己的 git 命令时锁定存储库。我已经在首选项中关闭了所有不必要的源代码控制选项(自动刷新本地状态、自动刷新服务器状态和自动添加和删除文件。)

我目前的策略是重试该命令直到它起作用,这很少需要多次尝试。

有没有办法让 Xcode 在创建 index.lock 的频率上不那么激进?

或者,有没有一种方法可以让 git 自动重试命令,直到它们以这种方式失败时才成功?

I can make git automatically retry commands until they succeed if they fail in this way?

不适用于本机 git:您需要编写一个 git 命令包装程序,它将循环并基本上等待 index.lock 消失(这类似于描述的等待策略在“Git - fatal: Unable to create '/path/my_project/.git/index.lock': File exists”)

的回答中

包装器可以:

  • 包含超时以避免无限期等待,
  • 尝试在超时和 try and kill it 时搜索 git 进程,以便最终释放该锁。

这就是,例如,IDE like SublimeText does

root = git_root(self.get_working_dir())
if wait_for_lock and root and os.path.exists(os.path.join(root, '.git', 'index.lock')):
    print("waiting for index.lock", command)
    do_when(lambda: not os.path.exists(os.path.join(root, '.git', 'index.lock')),
        self.run_command, command, callback=callback, show_status=show_status, filter_empty_args=filter_empty_args, no_save=no_save, wait_for_lock=wait_for_lock, **kwargs)

因为此文件是由 git 本身 创建 删除 的。
如果你想在创建时删除它,你需要在文件上设置一些 "watch",当你看到它时将其删除。

一个简单的解决方案是安装一些 "watch" 插件,它会在创建文件时 "capture"

有很多库和工具可以完成这项任务。


这里列出了一些:

inotify-tools

inotify-tools is a C library and a set of command-line programs for Linux providing a simple interface to inotify. These programs can be used to monitor and act upon filesystem events


fswatch

fswatch is a file change monitor that receives notifications when the contents of the specified files or directories are modified.

Usage example:

fswatch -o ~/path/to/watch | xargs -n1 ~/script/to/run/when/files/change.sh

watchdog

Python API and shell utilities to monitor file system events.

您可以使用 shell-command 子命令 执行 shell 命令以响应事件:

watchmedo shell-command \
    --patterns="*.lock" \
    --recursive \
    --command='rm index.lock' \
    .


您是 mac 用户,但 windows 用户可以安装以下任何程序,这些程序将在文件创建时进行监控

https://www.raymond.cc/blog/3-portable-tools-monitor-files-folders-changes/

正如其他人所说,git 没有任何原生内容,但 Chromium 开发人员做了一个名为 git-retry 的 python 脚本,由 shell 包装器调用。

而不是键入例如:

git commit 你会输入 git-retry commit

您可以通过克隆从他们的工具存储库中获取该工具:

https://chromium.googlesource.com/chromium/tools/depot_tools.git

这是我的 hacky 补丁:几行 bash 等待锁定文件消失,然后运行您的 git 命令。竞争条件当然是可能的,这不是防弹的,但在大多数情况下

function retry {
    while [ 1 == 1 ]; do
        if test -f /path/to/repo/.git/index.lock; then
            echo -n ".";
            sleep 0.5;
        else
            "$@";
            return;
        fi  
    done
}

你可以把它扔到你的 ~/.bashrc 中,然后使用它:

retry git commit -m "ohhh yeaaaa"

干杯!

我曾经使用 Xcode 的 git 客户端,它一直导致错误,包括这个,所以我已经停止使用 Xcode 来设置我的工作区或制作提交。为了启用此设置,我从 Xcode X.x 的命令行工具安装了 git 支持,并参考外部 git GUI 以获取任何导致更改的命令到我的本地或远程副本,包括切换分支。

自从我开始使用外部客户端以来,我对 index.lock 文件没有任何问题。 在执行罕见操作时,例如重置远程分支,或重命名分支机构,我使用终端。有一些免费的高质量 git 客户端,包括 SourceTree。

如果要在 Xcode 中使用外部 git 客户端和新项目,只需不要选择 git 工作区选项(如果显示)。相反,使用外部 git 客户端 'Add' 一个额外的 git 工作区,并选择 Xcode 项目的根目录。

作为旁注,当我这样做时,我通常有一个根目录来存放很多相关的杂项文件,这也是我的 Xcode 项目目录的主目录,它是我的根目录git 工作区。这允许我有笔记和其他我不想受版本控制的文件。

这是一个典型的设置:

    + Project Directory
    ---+ Xcode project directory (git root)
    ---- Other project files (not under source control)

希望对您有所帮助!