【问题标题】:How to programatically inspect remote tracking information upstream?如何以编程方式检查上游的远程跟踪信息?
【发布时间】:2022-01-16 06:22:05
【问题描述】:

我的问题类似于this one.

我将本地分支推送到服务器,在该服务器上首次创建它,并将其设置为本地分支的上游,使用--upstream。我无法以编程方式从上游提取跟踪信息,而无需对本地 git 存储库进行不必要的更改。比如想知道上游的HEAD指向的commit hash。

以下是我创建远程分支并将其设置为上游的方式:

$ git push --set-upstream sshname:/user/project.git

我可以git pullgit push 等等。但是,我的.bashrc 中有一个脚本,它检查上游服务器上最新提交的哈希并将其与我当前分支的哈希进行比较。 (这用于使用颜色方案美化提示,帮助我快速查看我是否记得将 repo 推送到服务器,或者我是否处于分离状态等)。该脚本在大多数本地存储库上都可以正常工作,在那里它使用远程HEAD 散列

$ git rev-parse "$(git branch --show-current 2> /dev/null)"@{upstream}

> fatal: upstream branch 'refs/heads/master' not stored as a remote-tracking branch

如您所见,它声称远程分支没有作为远程跟踪分支在本地存储。

我在 StackExchange 上寻找有关如何解决此问题的各种建议,包括 How to create git Remote-Tracking Branchlearning Git: tracking vs. setting upstream (-u) for remotes?。没有什么帮助。许多建议都是错误的,人们将remotesremote tracking branchesupstream urls 混为一谈。


这是人们可能建议的各种命令的输出:

$ git remote -vv
> [no output]
$ git branch -vva
> * master <HASH> <COMMIT_MSG>
$ git fetch -a
> From sshname:/user/project
 * branch            master     -> FETCH_HEAD

这是显示我正在寻找的信息的第一个。但它不是机器可解析的格式,也没有--porcelain这也是错误的。 真正的 URL 以.git 结尾。而且服务器确实需要这个.git 后缀;不容忽视。

$ git ls-remote
> From sshname:/user/project.git
<HASH>        HEAD
<HASH>        refs/heads/master

现在是正确的 URL,但同样不可机器解析。

我还可以运行“破坏性”操作(不适用于脚本),以便以类似的方式间接获取此信息:

$ git pull
> From sshname:/user/project
 * branch            master     -> FETCH_HEAD
Already up to date.

又是错误的网址。

$ git push
> Pushing to sshname:/user/project.git
To gitea:/murdock/dupmaster.git
 = [up to date]      master -> master
Everything up-to-date

不用说,我几乎不能相信脚本的这种不一致的输出。我需要一个类似porcelain 的输出。

现在我找到的最接近的解决方案是:

$ git config -l
> ...
branch.master.remote=sshname:/user/project.git
branch.master.merge=refs/heads/master

表明我可以通过这种方式获取上游“URL”:

$ git config --get branch.master.remote
> sshname:/user/project.git

但是,我仍然无法探测远程跟踪信息。手动,我可以根据这个“URL”添加一个 git 远程,然后运行git fetch -a,这(可能)会解决我的问题。但这是一个改变git repo 的“破坏性”过程。我正在尝试编写一些不会对存储库进行不必要更改的脚本。

如何在不更改 git 存储库的情况下以可靠的方式以编程方式获取跟踪信息?

如果可能的话,我会满足于自动创建远程跟踪分支。但我不想创建遥控器(如何自动命名它们?等等)。

【问题讨论】:

    标签: git


    【解决方案1】:

    这里的问题是您已经设置了一个 Git 存储库,其中 没有远程,如下所示:

    $ git remote -vv
    > [no output]
    

    没有远程,就没有远程跟踪名称。远程跟踪名称是通过从其他 Git 存储库获取分支名称​​ 生成的,如通过“远程”访问它找到的存储库中所见,并通过给定下提供的映射运行它远程。

    添加一个远程这个存储库:

    git remote add origin <url>
    

    (假设您想使用名称origin;在此处使用您喜欢的任何名称,但origin 是标准的第一个名称)。这将创建遥控器。遥控器现在存储 URL,因此:

    $ git config --get branch.master.remote
    > sshname:/user/project.git
    

    会改变的。

    为了实现这种改变,而不是(或之后):

    $ git push --set-upstream sshname:/user/project.git
    

    使用:

    git push --set-upstream origin master
    

    现在代替:

    $ git config --get branch.master.remote
    > sshname:/user/project.git
    

    你会发现branch.master.remote 只包含origin

    遥控器本身提供了一个默认的 fetch refspec:

    git config --get remote.origin.fetch
    

    将显示:

    +refs/heads/*:refs/remotes/origin/*
    

    随后的git fetch origin 操作将创建或更新refs/remotes/origin/ 命名空间中的名称:远程跟踪名称origin,其URL 存储在remote.origin.url 中。

    (发生的事情是,您使用的是 Primeval Git 的设置,早在 2005 年左右,在 remote 的概念被发明之前。没有遥控器,就没有遥控器- 跟踪名称。Git 仍然支持这种模式,但使用它是不明智的,因为——正如你所发现的——许多现代软件真的想要通过遥控器提供的功能。)

    【讨论】:

    • 感谢您的澄清。那么,你会说不建议使用git push -u host.name:/path/to/repo吗?相反,我们的工作流程应该是始终添加遥控器,然后使用 git push -u remote/branch 推送?
    • @Myridium:是的。仅当您不打算进一步使用原始 Git URL 时才使用它,否则将其保存为 git remote add 步骤。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多