如何正确强制 Git 推送?

发布于 2024-10-29 03:16:50 字数 763 浏览 13 评论 0 原文

我已经设置了一个远程非裸“主”存储库并将其克隆到我的计算机上。我进行了一些本地更改,更新了本地存储库,并将更改推送回远程存储库。到那时一切都很好。

现在,我必须更改远程存储库中的某些内容。然后我在本地仓库中更改了一些内容。我意识到不需要更改远程存储库。因此,我尝试从本地存储库 git Push 到远程存储库,但收到如下错误:

为了防止您丢失历史记录,非快进更新已 拒绝 再次推送之前合并远程更改。请参阅“注意事项” 有关详细信息,请参阅 git push --help 的快进部分。

我认为 a 可能

git push --force

会强制我的本地副本将更改推送到远程副本并使其相同。 它确实强制更新,但是当我返回到远程存储库并进行提交时,我注意到这些文件包含过时的更改(主远程存储库以前具有的更改)。

正如我在对其中一个答案的评论中提到的

[我]尝试强制,但是当返回主服务器保存更改时,我得到了过时的暂存。因此,当我提交时,存储库并不相同。当我再次尝试使用 git Push 时,我得到了同样的错误。

我该如何解决这个问题?

I've set up a remote non-bare "main" repo and cloned it to my computer. I made some local changes, updated my local repository, and pushed the changes back to my remote repo. Things were fine up to that point.

Now, I had to change something in the remote repo. Then I changed something in my local repo. I realized that the change to the remote repo was not needed. So I tried to git push from my local repo to my remote repo, but I got an error like:

To prevent you from losing history, non-fast-forward updates were
rejected Merge the remote changes before pushing again. See the 'Note
about fast-forwards' section of git push --help for details.

I thought that probably a

git push --force

would force my local copy to push changes to the remote one and make it the same. It does force the update, but when I go back to the remote repo and make a commit, I notice that the files contain outdated changes (ones that the main remote repo previously had).

As I mentioned in the comments to one of the answers:

[I] tried forcing, but when going back to master server to save the changes, i get outdated staging. Thus, when i commit the repositories are not the same. And when i try to use git push again, i get the same error.

How can I fix this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

-黛色若梦 2024-11-05 03:16:50

只需执行以下操作:

git push origin <your_branch_name> --force

或者如果您有特定的存储库:

git push https://git.... --force

这将删除您之前的提交并推送当前的提交。

它可能不正确,但如果有人偶然发现此页面,认为他们可能需要一个简单的解决方案...

短标志

另请注意,-f--force 的缩写>,所以

git push origin <your_branch_name> -f

也可以。

Just do:

git push origin <your_branch_name> --force

or if you have a specific repo:

git push https://git.... --force

This will delete your previous commit(s) and push your current one.

It may not be proper, but if anyone stumbles upon this page, thought they might want a simple solution...

Short flag

Also note that -f is short for --force, so

git push origin <your_branch_name> -f

will also work.

别想她 2024-11-05 03:16:50

如果 push --force 不起作用,您可以执行 push --delete。看一下这个实例的第二行:

git reset --hard HEAD~3  # reset current branch to 3 commits ago
git push origin master --delete  # do a very very bad bad thing
git push origin master  # regular push

但是要注意...

永远不要回顾公共 git 历史记录!

换句话说:

  • 永远不要强制推送公共存储库。
  • 不要做任何可能破坏某人拉力的事情。
  • 永远不要在某人可能已经拉取的存储库重置重写历史记录。

当然,即使这条规则也有极少数例外,但在大多数情况下,不需要这样做,而且会给其他人带来问题。

相反,执行恢复操作。

并且始终小心推送到公共存储库的内容。恢复:

git revert -n HEAD~3..HEAD  # prepare a new commit reverting last 3 commits
git commit -m "sorry - revert last 3 commits because I was not careful"
git push origin master  # regular push

实际上,两个原始 HEAD(来自恢复邪恶重置)将包含相同的文件。


编辑以添加有关 push --force 的更新信息和更多参数

考虑使用租约而不是推送来推动强制,但仍然更喜欢恢复

push --force 可能带来的另一个问题是何时有人在你之前推送任何东西,但在你已经获取之后。如果您现在强制使用您的rebased版本,您将取代其他人的工作

git push --force-with-lease rel="noreferrer">git 1.8.5 (感谢@VonC对该问题的评论)试图解决这个具体问题。基本上,如果自您最近一次获取以来远程被修改,它将带来错误并且不会推送。

如果您确实确定需要 push --force,但仍想防止更多问题,那么这很好。我想说这应该是默认的 push --force 行为。但这还远不是强制推动的借口。在您rebase之前获取的人仍然会遇到很多麻烦,如果您恢复,这些问题就可以轻松避免。

既然我们谈论的是 git --push 实例...

为什么有人想要强制推送?

@linquize 在评论中带来了一个很好的推力示例:敏感数据。您错误地泄露了不应推送的数据。如果你足够快,你可以通过强制推到顶部来“修复”*它。

* 数据仍将是在远程除非您还执行垃圾收集,或以某种方式清理它。显然,它也有可能被其他已经获取过它的人传播,但你明白了。

And if push --force doesn't work you can do push --delete. Look at 2nd line on this instance:

git reset --hard HEAD~3  # reset current branch to 3 commits ago
git push origin master --delete  # do a very very bad bad thing
git push origin master  # regular push

But beware...

Never ever go back on a public git history!

In other words:

  • Don't ever force push on a public repository.
  • Don't do this or anything that can break someone's pull.
  • Don't ever reset or rewrite history in a repo someone might have already pulled.

Of course there are exceptionally rare exceptions even to this rule, but in most cases it's not needed to do it and it will generate problems to everyone else.

Do a revert instead.

And always be careful with what you push to a public repo. Reverting:

git revert -n HEAD~3..HEAD  # prepare a new commit reverting last 3 commits
git commit -m "sorry - revert last 3 commits because I was not careful"
git push origin master  # regular push

In effect, both origin HEADs (from the revert and from the evil reset) will contain the same files.


edit to add updated info and more arguments around push --force

Consider pushing force with lease instead of push, but still prefer revert

Another problem push --force may bring is when someone push anything before you do, but after you've already fetched. If you push force your rebased version now you will replace work from others.

git push --force-with-lease introduced in the git 1.8.5 (thanks to @VonC comment on the question) tries to address this specific issue. Basically, it will bring an error and not push if the remote was modified since your latest fetch.

This is good if you're really sure a push --force is needed, but still want to prevent more problems. I'd go as far to say it should be the default push --force behaviour. But it's still far from being an excuse to force a push. People who fetched before your rebase will still have lots of troubles, which could be easily avoided if you had reverted instead.

And since we're talking about git --push instances...

Why would anyone want to force push?

@linquize brought a good push force example on the comments: sensitive data. You've wrongly leaked data that shouldn't be pushed. If you're fast enough, you can "fix"* it by forcing a push on top.

* The data will still be on the remote unless you also do a garbage collect, or clean it somehow. There is also the obvious potential for it to be spread by others who'd fetched it already, but you get the idea.

人│生佛魔见 2024-11-05 03:16:50

如果我在本地分支 A,并且我想强制将本地分支 B 推送到原始分支 CI 可以使用以下语法:

git push --force origin B:C

If I'm on my local branch A, and I want to force push local branch B to the origin branch C I can use the following syntax:

git push --force origin B:C
撑一把青伞 2024-11-05 03:16:50

使用以下命令:

git push -f origin master

use this following command:

git push -f origin master
最丧也最甜 2024-11-05 03:16:50

首先,我不会直接在“主”存储库中进行任何更改。如果你真的想要一个“主”存储库,那么你应该只推送它,而不是直接更改它。

关于您收到的错误,您是否尝试过从本地存储库中git pull,然后git push到主存储库?您当前正在做的事情(如果我理解得很好)是强制推送,然后丢失“主”存储库中的更改。您应该首先在本地合并更改。

First of all, I would not make any changes directly in the "main" repo. If you really want to have a "main" repo, then you should only push to it, never change it directly.

Regarding the error you are getting, have you tried git pull from your local repo, and then git push to the main repo? What you are currently doing (if I understood it well) is forcing the push and then losing your changes in the "main" repo. You should merge the changes locally first.

海之角 2024-11-05 03:16:50

尽管 git push --force-with-lease 是一个更安全的命令,但 git push --force 可以完成这项工作

。覆盖远程分支,而 git push --force-with-lease 则仅在本地副本知道远程分支上的所有提交时才覆盖远程分支。这种差异使得破坏其他人对项目的更改变得更加困难。

git push --force would do the job, although git push --force-with-lease is a safer command

git push --force overwrites the remote branch, while git push --force-with-lease only overwrites the remote branch if your local copy is aware of all of the commits on the remote branch. This difference makes it significantly more difficult to destroy someone else’s changes on the project.

长发绾君心 2024-11-05 03:16:50

使用 --force-with-lease 可能是一个更好的选择:

git push <remote> <branch> --force-with-lease

它确保(有一些警告 - 请阅读下文)在您修改分支之前没有人更新分支,因此您不会覆盖他们的改变。


详细了解 Git 文档

此选项允许您说出您期望的历史记录
更新是您重新定位并想要替换的内容。 如果远程参考
仍然指向您指定的提交,您可以确定没有
其他人对裁判做了任何事情
。这就像“租赁”
引用没有显式锁定它,并且远程引用被更新
仅当“租约”仍然有效时。

--force-with-lease 单独使用,无需指定详细信息,将通过要求其更新来保护所有将要更新的远程引用
当前值与我们的远程跟踪分支相同
他们。

关于安全性的一般说明:提供没有预期值的此选项,即作为 --force-with-lease--force-with-lease =<参考名称>
与隐式运行 git fetch 的任何东西交互非常糟糕
要在后台推送到的远程,例如 git fetch origin 在 cronjob 中的存储库上。

它通过 --force 提供的保护确保后续
你的工作不基于的改变不会被破坏,但这是
如果某些后台进程正在更新中的引用,则会被轻易击败
背景。除了远程跟踪信息之外,我们没有任何信息
作为您预计会看到和看到的裁判的启发式参考是
愿意去破坏。

如果你的编辑器或其他系统正在后台运行 git fetch ,缓解这种情况的方法就是简单地设置另一个
远程

Using --force-with-lease might be a better option:

git push <remote> <branch> --force-with-lease

It makes sure (with some caveats - read below) no one has updated the branch before you modified it, so you don't overwrite their changes.


Read more on Git documentation:

This option allows you to say that you expect the history you are
updating is what you rebased and want to replace. If the remote ref
still points at the commit you specified, you can be sure that no
other people did anything to the ref
. It is like taking a "lease" on
the ref without explicitly locking it, and the remote ref is updated
only if the "lease" is still valid.

--force-with-lease alone, without specifying the details, will protect all remote refs that are going to be updated by requiring their
current value to be the same as the remote-tracking branch we have for
them.

A general note on safety: supplying this option without an expected value, i.e. as --force-with-lease or --force-with-lease=<refname>
interacts very badly with anything that implicitly runs git fetch on
the remote to be pushed to in the background, e.g. git fetch origin on your repository in a cronjob.

The protection it offers over --force is ensuring that subsequent
changes your work wasn’t based on aren’t clobbered, but this is
trivially defeated if some background process is updating refs in the
background. We don’t have anything except the remote tracking info to
go by as a heuristic for refs you’re expected to have seen & are
willing to clobber.

If your editor or some other system is running git fetch in the background for you a way to mitigate this is to simply set up another
remote

剑心龙吟 2024-11-05 03:16:50

我真的建议:

  • 仅推送到主存储库

  • 确保主存储库是裸仓库,以免主仓库工作树不在其中时出现任何问题与其 .git 库同步。请参阅“如何推送本地 git存储库到另一台计算机?

  • 如果您必须在主(裸)存储库中进行修改,请克隆它(在主服务器上),进行修改并推送回它

换句话说,保持从主服务器和本地计算机都可以访问裸存储库,为了有一个上游仓库来从中拉取/拉取。

I would really recommend to:

  • push only to the main repo

  • make sure that main repo is a bare repo, in order to never have any problem with the main repo working tree being not in sync with its .git base. See "How to push a local git repository to another computer?"

  • If you do have to make modification in the main (bare) repo, clone it (on the main server), do your modification and push back to it

In other words, keep a bare repo accessible both from the main server and the local computer, in order to have a single upstream repo from/to which to pull/pull.

情独悲 2024-11-05 03:16:50

我也有同样的问题,但最后想通了。您最可能需要做的是运行以下两个 git 命令(用 git 提交修订号替换 hash):

git checkout <hash>
git push -f HEAD:master

I had the same question but figured it out finally. What you most likely need to do is run the following two git commands (replacing hash with the git commit revision number):

git checkout <hash>
git push -f HEAD:master
冷默言语 2024-11-05 03:16:50

如果您使用 Github 访问令牌进行身份验证,请尝试以下操作:

  • git remote set-url origin https://[电子邮件受保护]/UserName/ProjectName

  • git push --force --set-upstream origin master

if you are authenticating with Github access token, try this:

  • git remote set-url origin https://[email protected]/UserName/ProjectName

  • git push --force --set-upstream origin master

枯寂 2024-11-05 03:16:50

这是我们在维护历史记录的同时替换公司 gitHub 存储库上的 master 的解决方案。

通常会禁用 push -f 以掌握公司存储库以维护分支历史记录。这个解决方案对我们有用。

git fetch desiredOrigin
git checkout -b master desiredOrigin/master // get origin master

git checkout currentBranch  // move to target branch
git merge -s ours master  // merge using ours over master
// vim will open for the commit message
git checkout master  // move to master
git merge currentBranch  // merge resolved changes into master

将您的分支推送到 desiredOrigin 并创建 PR

This was our solution for replacing master on a corporate gitHub repository while maintaining history.

push -f to master on corporate repositories is often disabled to maintain branch history. This solution worked for us.

git fetch desiredOrigin
git checkout -b master desiredOrigin/master // get origin master

git checkout currentBranch  // move to target branch
git merge -s ours master  // merge using ours over master
// vim will open for the commit message
git checkout master  // move to master
git merge currentBranch  // merge resolved changes into master

push your branch to desiredOrigin and create a PR

你与清晨阳光 2024-11-05 03:16:50

我的问题是——我做了:

git checkout arbitrary_commit
git push origin master --force

这不是正确的做法。相反,我必须:

git reset HEAD~3
git push origin master --force

注意:数字 3 只是一个示例。你应该输入你自己的号码。

My issue was--I did:

git checkout arbitrary_commit
git push origin master --force

which was not the right thing to do. Instead I had to:

git reset HEAD~3
git push origin master --force

Note: the number 3 is just an example. You should put your own number.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文