为什么 Git 只是在没有 --force 标志的情况下执行强制更新?

Why did Git just perform a forced update without the --force flag?

昨天我们在工作中遇到了一件非常奇怪的事情。我对存储库进行了一些更改,提交并调用了 git push,就像我一直做的那样。事情是这样的:

user@host:~/path/to/repo$ git add file_a.h 
user@host:~/path/to/repo$ git add file_b.h
user@host:~/path/to/repo$ git add file_c
user@host:~/path/to/repo$ git add file_d.h
user@host:~/path/to/repo$ git commit
[master a9c4595] Perform change requested by customer.
 4 files changed, 4 insertions(+), 4 deletions(-)
user@host:~/path/to/repo$ git push
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Delta compression using up to 4 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 845 bytes | 845.00 KiB/s, done.
Total 9 (delta 8), reused 0 (delta 0)
To ssh://git.corp.com:port/project/repo.git
 + 38a09ed...a9c4595 master -> master (forced update)
 + 38a09ed...a9c4595 38 -> 38 (forced update)
user@host:~/path/to/repo$ git log

具体观察(forced update)注意那里。我的同事就在我之前将更改推送到此存储库,在我使用 Git 约 7 年的时间里,每次发生这种情况时,Git 都会警告我遥控器有我不知道的更改没有,并要求我先拉再推。 为什么现在没有发生这种情况? Git 而是删除了我同事在远程上的提交,并用我自己的 HEAD^ 替换了它。将来我将如何预防这种情况?

其他详细信息:我们的 Git 工作流程,在与其他项目的集成方面,依赖于标签,因此我们有一个 post-commit 挂钩,如下所示:

#!/bin/bash

tag_ver="$(git describe --tags --match 0 | cut -d'-' -f2)"

git rev-list HEAD | head -n1 | xargs git tag $tag_ver

所以每次提交时,它只是将标记递增一个。

正如您在 中所说:

I might have just found the culprit. git config -l revealed the following line: remote.origin.push=+refs/heads/*

确实是这个原因。正如 the git push documentation 所说:

When the command line does not specify what to push with <refspec>... arguments or --all, --mirror, --tags options, the command finds the default <refspec> by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push (See git-config(1) for the meaning of push.default).

出于 git push 目的,省略冒号的 refspec 有效地重复了 <src> 部分,因此您的 remote.origin.push 使 git push origin 表现得像 git push origin +refs/heads/*:refs/heads/* .前导 + 符号设置此 refspec 的强制标志。