繁体   English   中英

试图从 git 中删除身份验证会创建奇怪的合并冲突和不应该存在的更改

[英]Trying to remove authentication from git pull creating strange merge conflicts and changes that shouldn't exist

我编写了一个脚本来帮助自动化大型拉取请求以掌握 git。 我试图摆脱用户在执行诸如拉取更新分支之类的操作时需要登录的问题,所以我一直在试图弄清楚如何做到这一点。 所以,我最终在 Bitbucket 服务器中创建了一个个人令牌,看看我是否可以让它为自己工作,它确实有效。 个人令牌并不适用于所有人,但我希望制定出正确的语法来测试它。

我想出的命令是这样的:

subprocess.check_call(['git', 'pull']+[f'https://{username}:{MYTOKEN}@{repo_url}'], cwd=repo_path)

但是我从它那里得到了非常奇怪的行为,它从我制作的脚本中提取了一堆文件,然后是我没有触及的一堆文件。 在这两种情况下,我从来没有将任何东西推送到远程分支,或者提交本地分支。 舞台区也什么都没有。

所以,我尝试这个看看会发生什么,我得到了正确的行为,它说我的回购是最新的,没有什么可以拉的。 这与我一直在做的手动 git pull 相匹配,因为我实际上没有接触任何文件。 但它要求用户输入我试图摆脱的凭据。

subprocess.check_call('git pull',cwd=repo_path)

知道什么会导致这样的事情吗?

首先,让我说您通常不应该在这里使用git pull ,因为您正在编写一个不应该是交互式的脚本,并且git pull在运行第二个命令时尝试是交互式的。 (有一些方法可以解决这个问题,特别是在 Git 的现代版本中,但它有助于将事情分解成两个单独的步骤。)

除此之外,无论您是使用git pull运行git fetch ,还是运行git fetch自己,都有一个关键区别:

git <command>

git <command> https://username:password@bitbucket.server/path/to/repo

那就是第二个命令提供了一个 URL。 正如我们将看到的,这个关键区别实际上很重要。

第一个命令缺少任何 URL-or- origin参数,因此它根据当前分支查找远程,或者如果当前分支没有远程(或者没有当前分支,在处于分离 HEAD 状态)。 无论此处的命令是fetch还是pull都是如此,因为git pull使用您提供的参数调用git fetch 所以无论哪种方式,我们运行git fetch :一种方式没有额外的 arguments,另一种方式,使用 URL。

git fetch被赋予一个remote时,这会启用一些不错的功能。 特别是, git fetch将更新相应的远程跟踪名称 这不是问题的直接根源,但更新远程跟踪名称是一件好事。 提供 URL 可防止git fetch更新远程跟踪名称。 这并不重要,但它是一个你不能轻易解决的问题。 这只是要记住的一点:以后会是轻微的,但持续不断的烦恼。

不过,更重要的是,这会影响git pull运行的第二个命令。 git fetch完成时,它会在 Git 存储库目录中写入一个名为FETCH_HEAD的文件(通常为.git )。 当使用远程运行git fetch时,我们最终得到如下内容:

$ cat .git/FETCH_HEAD
1c52ecf4ba0f4f7af72775695fee653f50737c71        branch 'master' of <url>
898f80736c75878acc02dc55672317fcc0e0a5a6    not-for-merge   branch 'maint' of <url>
bcca9488540da62a407e744ef77a8abcf8e92efe    not-for-merge   branch 'next' of <url>
1c4d5706c6ff6a04567b24d4b3168b09793a83f9    not-for-merge   branch 'seen' of <url>
32af5571f1841d138c786b68d4ec8c6a07752540    not-for-merge   branch 'todo' of <url>
a8eaf9de52c2d49799d7dc724e688ccbfa74390c    not-for-merge   tag 'v2.30.0-rc0' of <url>

当我们使用 URL 运行相同的命令时——甚至是git fetch origin将使用的相同的 URL 时——我们会得到:

1c52ecf4ba0f4f7af72775695fee653f50737c71        <url>

请注意,所有不同的分支名称,以及在下一步应该忽略的分支名称上的not-for-merge行都丢失了。 FETCH_HEAD文件中唯一的 hash ID 是与给定url的另一个 Git 存储库中的HEAD对应的 ID。

这可能是 go 出错的地方

git pull运行的第二个命令是:

git <command> <options> <hash>

这里的command部分通常是git mergegit rebase之一(这里有一种非常特殊的情况不适用于这两种情况都不适用)。 options取决于命令,因为git merge获得-m选项,而git rebase没有(但可以获得其他选项)。 hash是这里真正的问题。

git pull的 hash ID 提供给git merge .git/FETCH_HEAD git rebase输出。 使用远程时,该文件的一个特定行将对应于当前分支上游,即 Git 将使用的 hash ID。 But when git fetch was given a URL instead of a branch name, the fetch command wrote only one hash ID: that of the other Git repository's HEAD . 如果这不是正确的 hash ID,您的第二个命令将使用错误的 hash ID。

这几乎肯定是正在发生的事情。

如何解决这个问题

您可以通过以下方式修复它:

  • git pull提供正确的名称,以便它可以将其传递给git fetch和/或
  • 运行git fetch自己,然后根据需要自己运行第二个 Git 命令。

鉴于git pull设计为交互式,因此会根据用户的偏好配置设置更改其行为方式,我建议同时执行以下操作:运行git fetch自己,然后找出您要运行的第二个命令。

获取可能仍需要访问令牌。 (顺便提一下,在命令行上传递它会使访问令牌对机器上的其他进程可读,所以它不是很安全。设置一个保存令牌的遥控器可能更安全一些,在文件是安全的,然后使用远程名称。远程名称将控制远程跟踪名称,这仍然是我前面提到的持续烦恼。对此有进一步的解决方法,但是一旦你有了一些远程跟踪名称,烦恼级别确实相当低,这可能已经足够了。)但是现在,无论您如何操作,它都可以在其他 Git 存储库中获取您想要解析的任何分支或标签的名称,从而找到正确的提交。

第二个命令仍然可以是git merge ,可能使用--ff-only或 rebase,检查它是否成功并在失败时回滚 - 或者甚至可能是git checkout以使用分离的 HEAD 而不是尝试更改任何本地存储库中的现有分支名称。 不过,重要的是,通过了解git pull的真正含义是获取,然后运行第二个命令,并了解此处的各种选项,您可以控制这两个操作的所有部分。 您不会因为使用错误的选项和/或错误的分支名称而随心所欲地使用git pull

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM