git push 命令用于将本地存储库内容上传到远程存储库。推送是将提交从本地存储库传输到远程代码存储库的方式。它所对应的是 git fetch,但获取是将提交导入本地分支,而推送则是将提交导出到远程分支。我们使用 git remote 命令对远程分支进行配置。推送有可能会覆盖变更,请在推送时小心谨慎。下面我们将讨论这些问题。

git push 用法

git push <remote> <branch>

将指定的分支以及所有必需的提交和内部对象推送到 <remote>。这将在目标存储库中创建本地分支。为了防止您覆盖提交,如果推送会导致目标存储库中出现非快进合并,git 将不允许您进行推送。

git push <remote> --force

与上面的命令相同,但是即使推送会导致非快进合并,git 也会强制推送。除非您完全确定自己在做什么,否则不要使用 --force 标志。

git push <remote> --all

将所有本地分支推送到指定的远程。

git push <remote> --tags

当您推送分支或使用 --all 选项时,标签不会自动推送。--tags 标志会将您的所有本地标签发送到远程存储库。

git push 讨论

git push 最常用于将本地变更发布到中央存储库。修改本地存储库后,您可以执行推送来与远程团队成员共享所做的修改。

使用 git push 发布变更

上图显示了当本地 master 的进度超过了中央存储库的 master,并且您通过运行 git push origin master 发布了变更时所发生的情况。请注意,git push 与从远程存储库内部运行 git merge master 在本质上是相同的。

git push 和同步

git push 是整个Git“同步”过程中使用的诸多组件之一。同步命令在使用 git remote 命令进行配置的远程分支上运行。git push 可以被看作是“上传”命令,而 git fetch 和 git pull 可以被视为“下载”命令。一旦变更集合已通过下载或上传移动,您就可以在目的地执行git merge 来集成变更。

推送到裸存储库

一种常用的现代 Git 做法是,让远程托管的 --bare 存储库充当中央源存储库。此源存储库通常由可信任的第三方(例如 Bitbucket)在异地托管。由于推送会干扰远程分支结构,因此最安全和最常见的做法是推送到使用 --bare 标志创建的存储库。裸代码存储库没有工作目录,因此推送不会更改任何进行中的工作目录内容。有关创建裸存储库的更多信息,请阅读有关 git init 的内容。

强制推送

如果推送请求会导致非快进合并,那么 Git 会通过拒绝这些请求来防止您覆盖中央存储库的历史记录。因此,如果远程历史记录与您的历史记录有所不同,您需要拉取远程分支并将其合并到本地分支中,然后再尝试推送。这类似于您借助 SVN 在提交变更集合之前通过 svn update 与中央存储库进行同步的方式。

--force 标志会覆盖此行为,并使远程存储库的分支与本地分支相匹配,同时删除自上次拉取以来可能发生的任何上游变更。您唯一需要进行强制推送的时候是,当您意识到刚刚共享的提交并不十分正确,并且您使用 git commit --amend 或交互式变基对它们进行了修复。但是,您必须完全确定,在使用 --force 选项之前,您的队友们都没有拉取这些提交。

示例

默认的 git push

以下示例描述了将本地贡献发布到中央存储库的标准方法之一。首先,通过获取中央存储库的副本并将您的变更变基到本地主分支之上,从而确保您的本地主分支是最新的。交互式变基也是一个在共享提交之前对其进行清理的好机会。然后,git push 命令会将本地主分支上的所有提交都发送至中央存储库。

git checkout master
git fetch origin master
git rebase -i origin/master
# Squash commits, fix up commit messages etc.
git push origin master

我们已经确保本地主分支是最新的,因此这将引发快进合并,而且 git push 应该不会再出现上面的非快进合并问题。

修改后的强制推送

git commit 命令可接受 --amend 选项,该选项将更新先前的提交。我们常常会对提交进行修改,来更新提交消息或添加新变更。一旦修改了提交,git push 就会失败,因为 git 会将修改后的提交和远程提交视为不同的内容。推送修改后的提交时必须使用 --force 选项。

# make changes to a repo and git add
git commit --amend
# update the existing commit message
git push --force origin master

上面的示例假设相关操作是在具有提交历史记录的现有存储库上执行的。我们使用 git commit --amend 来更新先前的提交,然后使用 --force 选项来强制推送修改后的提交。

删除远程分支或标签

有时,出于记账或组织性目的,我们需要清理分支。要完全删除一个分支,必须在本地和远程都将其删除。

git branch -D branch_name
git push origin :branch_name

上面的示例操作将删除名为 branch_name 的远程分支。将带有冒号前缀的分支名称传递给 git push 会删除该远程分支。