gpt4 book ai didi

git - 放入目录(cd)和使用 `work-tree`参数之间的Git有什么区别?

转载 作者:行者123 更新时间:2023-12-03 14:25:27 25 4
gpt4 key购买 nike

我正在使用PHP在PHP的exec中运行Git,以获取有关一些服务器仪表板的某些Git项目的信息。我遇到了一些奇怪的输出,这使我想知道我是否误解了“工作树”是什么。

如果使用此命令,请将%s sprintf参数替换为Git项目的路径:

git --work-tree=%s status

然后我得到以下输出:
On branch server-dashboard
Your branch is ahead of 'origin/server-dashboard' by 1 commit.
(use "git push" to publish your local commits)

Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: .gitignore
deleted: README.md
deleted: common.php
deleted: conf/dev/settings.ini
deleted: conf/prod/settings.ini
deleted: conf/settings.ini.example
deleted: lib/HealthSettings.php
deleted: lib/Settings.php
deleted: public/assets/main.css
deleted: public/assets/main.js
deleted: public/assets/refresh.gif
deleted: public/assets/spinner.gif
deleted: public/curl-test.php
deleted: public/dashboard.php
deleted: public/iframes.php
modified: public/index.php
deleted: public/info.php
deleted: public/no-servers.php
deleted: public/sections/apache-mods.php
deleted: public/sections/curl-headers.php
deleted: public/sections/curl-self.php
deleted: public/sections/database.php
deleted: public/sections/env.php
deleted: public/sections/git-table.php
deleted: public/sections/git.php
deleted: public/sections/php-exts.php
deleted: public/sections/php-proxy.php
deleted: public/sections/tableau-proxy-table.php
deleted: public/sections/tableau-proxy.php
deleted: public/sections/user.php
deleted: public/tabs.php

那不是我期望的,因为如果我在控制台上运行 git status,那不是我得到的。

现在,如果我在PHP中运行此命令(再次将字符串参数替换为路径):
cd %s && git status

然后我得到正确的输出:
On branch master
Your branch is ahead of 'origin/master' by 17 commits.
(use "git push" to publish your local commits)

nothing to commit, working tree clean

我猜想由于该项目比master提交少了17个提交,因此“错误”输出实际上是这些提交所发生的变化的表达。但是,我会认为这两个命令是等效的。我是不是错了,如果可以,我可以以编程方式运行Git命令而不必先使用 cd吗?

最佳答案

cd path; git commandgit --work-tree=path command之间有许多实质性的区别。可以根据其他参数和/或环境变量使这些差异中的一些或全部消失。

重要的是要意识到,Git几乎必须始终使用三个(而不是两个)关键项目。这些都是:

  • 存储库本身(名称到哈希ID对的 repo 数据库,例如表示提交master或其他任何哈希ID的e3331758f12da22f4103eec7efe1b5304a9be5e9,以及ID是该丑陋的哈希ID大字符串的对象)。该存储库通常位于工作树顶层的名为.git的目录中。这是git目录($GIT_DIR)。
  • 索引,该索引对工作树进行索引和缓存(因此对其两个名称进行索引或有时对其进行缓存),并用作更新文件的存储位置(因此称为其第三名称,暂存区)(实际上是路径名到Blob哈希ID的转换) ),当您打算建立一个新的提交时。该索引主要是一个文件:.git/index。从该路径名可以看到,默认情况下,索引文件位于存储库中。但是,它具有自己的单独的控制变量$GIT_INDEX_FILE。它只是默认为$GIT_DIR/index
  • 工作树以未压缩格式保存文件。通过将文件从提交中提取到索引中,然后从索引(仍在其中进行压缩,并且仅使用Git格式)将文件提取到工作树中,从而使文件进入工作树。工作树还可能包含索引中找不到的其他文件。此类文件是未暂存的。未暂存的文件可能会也可能不会被忽略(暂存文件,即其路径名出现在索引中的文件,根据定义是永远不会忽略的)。

  • 工作树通常只是当前工作目录,或者是从当前工作目录(通过向上步行( ..,然后是 ../..,依此类推),以查找包含 .git存储库目录的第一个位置)派生而来的。这意味着 cd path; git ...从您登陆的任何地方开始搜索工作树。

    如果没有覆盖,找到工作树并找到 .git目录,Git现在就会知道 $GIT_DIR在哪里以及在哪里找到索引文件。但是,如果使用 git --work-tree=path或通过设置环境变量 $GIT_WORK_TREE提供覆盖,则Git将在此处查找工作树,并在当前目录(或 ..,然后是 ../..等)中查找存储库目录。

    如果提供 --git-dir=path覆盖,或设置环境变量 $GIT_DIR,则Git会在此处查找存储库目录,而不管工作树的任何设置或缺少设置。

    (注意: --git-dir--work-tree实际上是通过让 git前端设置环境变量来实现的。因此,如果您同时设置了这两个参数,则flag参数将在Git命令的持续时间内覆盖环境设置,包括Git本身运行的任何子进程。)

    如果您通过环境提供了 $GIT_INDEX_FILE覆盖,则Git会在此处查找索引文件,而不管 $GIT_DIR的任何设置或缺少设置。

    这些设置中的任何一个都可以是绝对路径(相对路径),它是绝对路径(在类似Unix的系统上以 /开头,或者在更静音的系统上使用驱动器号)。绝对路径将覆盖当前工作目录,而相对路径将从当前工作目录开始。

    因此,任何这些参数或环境变量的确切内容都非常重要。例如,运行:
    cd $HOME/foo; GIT_INDEX_FILE=$HOME/index git --git-dir=sub/.git --work-tree=/tmp ...

    将导致Git在 $HOME/foo/sub/.git中寻找存储库,在 $HOME/index中寻找索引文件,在/tmp中寻找工作树。

    除此之外,前端 git命令还允许使用 -C参数或多个 -C参数。这些使Git都执行 cd到提供的路径。因此,以上内容大致等同于:
    GIT_INDEX_FILE=$HOME/index git -C $HOME/foo --git-dir=sub/.git --work-tree=/tmp ...

    除了以上命令终止后,shell/命令解释器仍保留在运行命令之前的任何工作目录中。 (我相信这些细节在Windows上会略有不同,因为Windows对“当前目录”与“当前驱动器号”或类似内容做出了一些非常奇怪的假设。)

    在您的特定情况下(运行 git status),请注意 git status进行两个单独的比较:
  • 首先,它将(通过git diff找到的)当前提交与$GIT_DIR/HEAD的内容进行比较(la $GIT_INDEX_FILE)。无论有什么不同,这里都会进行提交。
  • 然后,它将索引文件的内容与git diff的内容进行比较(再次称为$GIT_WORK_TREE)。不管有什么不同,这里都不会进行提交。

  • 前面和/或后面的计数来自较早的步骤,其中 git status使用当前分支(再次从 $GIT_DIR/HEAD进行)。通常,此 HEAD文件是一个符号引用,其中包含当前分支的名称。然后,Git可以找到分支的上游设置( git rev-parse --symbolic-full-name $branch@{upstream},或多或少,尽管 --abbrev-ref更适合人类): master通常以 refs/remotes/origin/master作为其上游。然后,Git读取从 $GIT_DIR中提取的提交图,以发现 masterorigin/master之间有多少个提交。

    以上并非全部。请查阅 git front end command documentation以查找可用于覆盖特定项目的更完整的环境变量列表。例如, GIT_ALTERNATE_OBJECT_DIRECTORIES可用于使Git在存储库本身之外查找其他对象存储位置,而 GIT_CEILING_DIRECTORIES可用于限制Git在浏览 ..../..等时进行的路径遍历。

    关于git - 放入目录(cd)和使用 `work-tree`参数之间的Git有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51500812/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com