今天 pull 代码的时候碰到以下问题(隐去了一些公司敏感信息):
XXX@CN-00012645 MINGW64 /c/Gerrard/Workspace/XXX (master) $ git pull error: cannot lock ref 'refs/remotes/origin/feature/hy78861': is at d4244546c8cc3827491cc82878a23c708fd0401d but expected a6a00bf2e92620d0e06790122bab5aeee01079bf From ssh://XXX ! a6a00bf2e92..f34729ba17a feature/hy78861 -> origin/feature/hy78861 (unable to update local ref)
方案一
这里首先是你的 feature/hy78861 这个分支出现了问题,由于你现在在 master 分支,如果只需要拉下来 master 的代码,那可以用以下命令作为替代:
XXX@CN-00012645 MINGW64 /c/Gerrard/Workspace/XXX (master) $ git pull origin master From ssh://XXX * branch master -> FETCH_HEAD ...... Current branch master is up to date.
- 由于 git pull 会把所有 remote 的信息全部拉下来,包括那个出错的分支 feature/hy78861,所以只 pull 你需要的分支信息就可以了。
- 这是一个治标的办法,这样一来你每一次 pull 都需要带上分支信息,没办法一键同步所有的远程分支信息。
方案二
要治本需要了解问题的根本原因,看上面的 log 信息,应该是分支索引 id 的信息紊乱。
所以我们先搜一下 a6a00bf2e92620d0e06790122bab5aeee01079bf 的信息:
XXX@CN-00012645 MINGW64 /c/Gerrard/Workspace/XXX (master) $ grep -ri 'a6a00bf2e92620d0e06790122bab5aeee01079bf' .git/info/refs:a6a00bf2e92620d0e06790122bab5aeee01079bf refs/remotes/origin/feature/hy78861 .git/logs/refs/remotes/origin/feature/HY78861:214f906ff67841712d6082f1a471cae91385cf2c a6a00bf2e92620d0e06790122bab5aeee01079bf XXX 1616051165 +0800 pull: fast-forward .git/logs/refs/remotes/origin/feature/HY78861:a6a00bf2e92620d0e06790122bab5aeee01079bf d4244546c8cc3827491cc82878a23c708fd0401d XXX 1623054120 +0800 pull: forced-update .git/packed-refs:a6a00bf2e92620d0e06790122bab5aeee01079bf refs/remotes/origin/feature/hy78861
然后搜一下 d4244546c8cc3827491cc82878a23c708fd0401d 的信息:
XXX@CN-00012645 MINGW64 /c/Gerrard/Workspace/XXX (master) $ grep -ri 'd4244546c8cc3827491cc82878a23c708fd0401d' .git/logs/refs/remotes/origin/feature/HY78861:efaa737003ebf53deb81ba78cf62d395a6a03a0b d4244546c8cc3827491cc82878a23c708fd0401d XXX 1614914234 +0800 pull: fast-forward .git/logs/refs/remotes/origin/feature/HY78861:d4244546c8cc3827491cc82878a23c708fd0401d f9650914c7a0fd3987a0dc106824d99c435297e3 XXX 1615431235 +0800 pull: storing head .git/logs/refs/remotes/origin/feature/HY78861:c62e20a4c3a8a3860a915a8559cbf167da18a16f d4244546c8cc3827491cc82878a23c708fd0401d XXX 1616051205 +0800 pull: fast-forward .git/logs/refs/remotes/origin/feature/HY78861:c62e20a4c3a8a3860a915a8559cbf167da18a16f d4244546c8cc3827491cc82878a23c708fd0401d XXX 1623053561 +0800 fetch: fast-forward .git/logs/refs/remotes/origin/feature/HY78861:a6a00bf2e92620d0e06790122bab5aeee01079bf d4244546c8cc3827491cc82878a23c708fd0401d XXX 1623054120 +0800 pull: forced-update .git/refs/remotes/origin/feature/HY78861:d4244546c8cc3827491cc82878a23c708fd0401d
最后再去 Gerrit 仓库,看一下这个 repo 的分支信息(我把一些信息抹掉了):
问题显然出在 feature/HY78861 和 feature/hy78861 上面,推测根本原因是:
- 这两个 feature branch 都是在外国的同事创建的,他们的工作环境是 Linux 系统,而中国的工作环境是 Windows 系统,再加上他们可能做了些不知道什么的骚操作,由于系统差异导致问题。
我们重新观察错误信息:
cannot lock ref 'refs/remotes/origin/feature/hy78861': is at d4244546c8cc3827491cc82878a23c708fd0401d
看一下我们的本地文件 C:GerrardWorkspaceXXX.git efs emotesoriginfeatureHY78861(注意这里是大写),文件内容是 :
- d4244546c8cc3827491cc82878a23c708fd0401d
显然这就是错误里面定位的内容,那么是不是把这个文件里面的内容改成 expected 就行了呢?
很可惜,失败了:
XXX@CN-00012645 MINGW64 /c/Gerrard/Workspace/EXXX (master) $ git pull From ssh://XXX + a6a00bf2e92...d4244546c8c feature/HY78861 -> origin/feature/HY78861 (forced update) error: cannot lock ref 'refs/remotes/origin/feature/hy78861': is at d4244546c8cc3827491cc82878a23c708fd0401d but expected a6a00bf2e92620d0e06790122bab5aeee01079bf ! a6a00bf2e92..f34729ba17a feature/hy78861 -> origin/feature/hy78861 (unable to update local ref)
这里文件中的信息,被强制从 a6a00bf2e92620d0e06790122bab5aeee01079bf 复原成了 d4244546c8cc3827491cc82878a23c708fd0401d。
这里我们总结一下问题:
- HY78861 分支 remote 上的 id 是 d4244546c8cc3827491cc82878a23c708fd0401d
- hy78861 分支 remote 上的 id 是 f34729ba17a48c9628dff31f8c6720843c6d1a74
- id a6a00bf2e92620d0e06790122bab5aeee01079bf 来源未知,可能就是由于外国同事的某些骚操作引起的,可能是一个过期的 id 值,后来被上面的某一个覆盖了
- C:GerrardWorkspaceXXX.git efs emotesoriginfeature 这个文件目录下面,由于 Windows 系统的关系,只能存在 HY78861 或者 hy78861 两个文件之一
所以我们这里就有方案了:
- 根据上面的记录,保证 HY78861 和 hy78861 的分支映射关系正确,一共两处:packed-refs 和 info/refs。
- C:GerrardWorkspaceXXX.git efs emotesoriginfeature 这个目录下面,保留一个 hy78864 或者 HY78864 文件,里面的内容随意,因为在执行 git pull 命令时会被覆盖。
- 如果是 HY78864,内容会变成 d4244546c8cc3827491cc82878a23c708fd0401d;如果是 hy78861,内容会变成 f34729ba17a48c9628dff31f8c6720843c6d1a74。
最后,git pull 执行成功
XXX@CN-00012645 MINGW64 /c/Gerrard/Workspace/XXX (master) $ git pull From ssh://XXX + f34729ba17a...d4244546c8c feature/HY78861 -> origin/feature/HY78861 (forced update) Already up to date. Current branch master is up to date.
方案三
最简单的方案,找个能够正确执行 git pull 命令的同事,把他的 .git 文件夹整个 copy 过来,看一下里面的 config 文件有什么私人信息,改掉就行。