远程仓库操作
git clone
远程仓库:
git clone
远程使用虚线表示
本地仓库多了一个名为 o/master 的分支, 这种类型的分支就叫远程分支。远程分支反映了远程仓库(在你上次和它通信时)的状态。
远程分支有一个特别的属性,在你检出时自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果。
为什么有 o/?
远程分支有一个命名规范 —— 它们的格式是:
<remote name>/<branch name>
因此,如果你看到一个名为 o/master 的分支,那么这个分支就叫 master,远程仓库的名称就是 o。
大多数的开发人员会将它们主要的远程仓库命名为 origin,并不是 o。这是因为当你用 git clone 某个仓库时,Git 已经帮你把远程仓库的名称设置为 origin 了不过 origin 对于我们的 UI 来说太长了,因此不得不使用简写 o 😃 但是要记住, 当你使用真正的 Git 时, 你的远程仓库默认为 origin!
Git 变成了分离 HEAD 状态,当添加新的提交时 o/master 也不会更新。这是因为 o/master 只有在远程仓库中相应的分支更新了以后才会更新。
git checkout o/master
git commit
git fetch
当我们从远程仓库获取数据时, 远程分支也会更新以反映最新的远程仓库。
解释 git fetch 前,我们先看看实例。这里我们有一个远程仓库, 它有两个我们本地仓库中没有的提交。
C2,C3 被下载到了本地仓库,同时远程分支 o/master 也被更新,反映到了这一变化
git fetch 完成了仅有的但是很重要的两步:
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如 o/master)
git fetch 通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。
git fetch 并不会改变你本地仓库的状态。它不会更新你的 master 分支,也不会修改你磁盘上的文件。
所以, 你可以将 git fetch 的理解为单纯的下载操作。
git fetch 参数
git fetch 的参数和 git push 极其相似。他们的概念是相同的,只是方向相反罢了(因为现在你是下载,而非上传)
git fetch origin foo
我们只下载了远程仓库中 foo 分支中的最新提交记录,并更新了 o/foo
可能在 foo 分支上的工作还未完成,你也不想弄乱它。
source 现在指的是远程仓库中的位置,而
git fetch foo~1:bar
Git 将 foo~1 解析成一个 origin 仓库的位置,然后将那些提交记录下载到了本地的 bar 分支(一个本地分支)上。注意由于我们指定了目标分支,foo 和 o/foo 都没有被更新。
如果执行命令前目标分支不存在会怎样呢?我们看一下上个对话框中没有 bar 分支的情况。跟 git push 一样,Git 会在 fetch 前自己创建立本地分支, 就像是 Git 在 push 时,如果远程仓库中不存在目标分支,会自己在建立一样。
如果 git fetch 没有参数,它会下载所有的提交记录到各个远程分支……
git fetch origin master~1:foo
git fetch origin foo:master
git checkout foo
git merge master
古怪的
Git 有两种关于
git push origin :side
git fetch origin :bugFix
通过给 push 传空值 source,成功删除了远程仓库中的 foo 分支
git push origin :foo
如果 fetch 空 到本地,会在本地创建一个新分支。
git fetch origin :bar
git pull
当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。
git cherry-pick o/master
git rebase o/master
git merge o/master
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作。它就是我们要讲的 git pull。
先来看看 fetch、merge 依次执行的效果
我们用 fetch 下载了 C3, 然后通过 git merge o/master
合并了这一提交记录。现在我们的 master 分支包含了远程仓库中的更新(在本例中远程仓库名为 origin)
等价于git pull
git pull参数
git pull 到头来就是 fetch 后跟 merge 的缩写。你可以理解为用同样的参数执行 git fetch,然后再 merge 你所抓取到的提交记录。
以下命令在 Git 中是等效的:
git pull origin foo 相当于:
git fetch origin foo; git merge o/foo
git pull origin bar~1:bugFix 相当于:
git fetch origin bar~1:bugFix; git merge bugFix
案例一:不同本地额远程分支合并
git pull 实际上就是 fetch + merge 的缩写, git pull 唯一关注的是提交最终合并到哪里(也就是为 git fetch 所提供的 destination 参数)
git merge origin master
通过指定 master 我们更新了 o/master。然后将 o/master merge 到我们的检出位置,无论我们当前检出的位置是哪。
案例二:merge到本地不存在的分支
git pull origin master:foo
它先在本地创建了一个叫 foo 的分支,从远程仓库中的 master 分支中下载提交记录,并合并到 foo,然后再 merge 到我们的当前检出的分支 bar 上。
案例三:
git pull origin bar:foo
git pull origin master:side
git push
git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。它的默认值取决于你正使用的 Git 的版本,
git push
git push <remote> <place>
Git 是通过当前检出分支的属性来确定远程仓库以及要 push 的目的地的。这是未指定参数时的行为,我们可以为 push 指定参数,语法是:
git push <remote> <place>
git push origin master
git checkout c0
git push origin master
分离头指针的时候直接push不会有任何的提交
如果不指定master:
git checkout c0
git push
命令失败了(正如你看到的,什么也没有发生)! 因为我们所检出的 HEAD 没有跟踪任何分支。
git push origin master
git push origin foo
git push origin <source>:<destination>
当为 git push 指定 place 参数为 master 时,我们同时指定了提交记录的来源和去向。
你可能想问 —— 如果来源和去向分支的名称不同呢?比如你想把本地的 foo 分支推送到远程仓库中的 bar 分支。
要同时为源和目的地指定
这个参数实际的值是个 refspec,“refspec” 是一个自造的词,意思是 Git 能识别的位置(比如分支 foo 或者 HEAD~1)
source 可以是任何 Git 能识别的位置
git push origin foo^:master
但是它确实是可以运行的 —— Git 将 foo^ 解析为一个位置,上传所有未被包含到远程仓库里 master 分支中的提交记录。
如果你要推送到的目的分支不存在会怎么样呢?没问题!Git 会在远程仓库中根据你提供的名称帮你创建这个分支!
git push origin master:newBranch
git push origin foo:master
git push origin master^:foo
历史偏离
因为这情况(历史偏离)有许多的不确定性,Git 是不会允许你 push 变更的。
你需要做的就是使你的工作基于最新的远程分支。
有许多方法做到这一点呢,不过最直接的方法就是通过 rebase 调整你的工作
我们用 git fetch 更新了本地仓库中的远程分支,然后用 rebase 将我们的工作移动到最新的提交记录下,最后再用 git push 推送到远程仓库。
git fetch
git rebase o/master
git push
变基的时候是需要解决冲突的,
尽管 git merge 不会移动你的工作(它会创建新的合并提交),但是它会告诉 Git 你已经合并了远程仓库的所有变更。这是因为远程分支现在是你本地分支的祖先,也就是说你的提交已经包含了远程分支的所有变化。
git fetch
git merge o/master
git push
当然 —— 前面已经介绍过 git pull 就是 fetch 和 merge 的简写,类似的 git pull --rebase 就是 fetch 和 rebase 的简写!
git pull
git pull --rebase
git push
git fetch
git merge
git push
git fetch
git rebase
git push
由 fetch、rebase/merge 和 push 组成的工作流很普遍。
远程服务器拒绝!(Remote Rejected)
如果你是在一个大的合作团队中工作, 很可能是master被锁定了, 需要一些Pull Request流程来合并修改。如果你直接提交(commit)到本地master, 然后试图推送(push)修改, 你将会收到这样类似的信息:
! [远程服务器拒绝] master -> master (TF402455: 不允许推送(push)这个分支; 你必须使用pull request来更新这个分支.)
远程服务器拒绝直接推送(push)提交到master, 因为策略配置要求 pull requests 来提交更新.你应该按照流程,新建一个分支, 推送(push)这个分支并申请pull request,但是你忘记并直接提交给了master.现在你卡住并且无法推送你的更新.
新建一个分支feature, 推送到远程服务器. 然后reset你的master分支和远程服务器保持一致, 否则下次你pull并且他人的提交和你冲突的时候就会有问题.
git reset --hard o/master
git checkout -b feature c2
git push origin feature
合并特性分支
这里共有三个特性分支 —— side1 side2 和 side3
我需要将这三分支按顺序推送到远程仓库
因为远程仓库已经被更新过了,所以我们还要把那些工作合并过来
git fetch
git rebase c8 side1
git rebase side1 side2
git rebase side2 side3
git rebase side3 master
git push
为什么不用 merge 呢?
优点:Rebase 使你的提交树变得很干净, 所有的提交都在一条线上
缺点:Rebase 修改了提交树的历史
git checkout master
git pull
git merge side1
git merge side2
git merge side3
git push
远程跟踪分支
master 和 o/master 的关联关系就是由分支的“remote tracking”属性决定的。master 被设定为跟踪 o/master,当你克隆仓库的时候, Git 就自动帮你把这个属性设置好了。当你克隆时, Git 会为远程仓库中的每个分支在本地仓库中创建一个远程分支(比如 o/master)。然后再创建一个跟踪远程仓库中活动分支的本地分支,默认情况下这个本地分支会被命名为 master。
可以让任意分支跟踪 o/master, 然后该分支会像 master 分支一样得到隐含的 push 目的地以及 merge 的目标。 这意味着你可以在分支 totallyNotMaster 上执行 git push,将工作推送到远程仓库的 master 分支上。
通过远程分支checkout一个新分支
有两种方法设置这个属性,第一种就是通过远程分支检出一个新的分支,执行:
**git checkout -b totallyNotMaster o/master**
就可以创建一个名为 totallyNotMaster 的分支,它跟踪远程分支 o/master。
我们检出一个名叫 foo 的新分支,让其跟踪远程仓库中的 master
git checkout -f foo o/master
git pull
我们使用了隐含的目标 o/master 来更新 foo 分支。需要注意的是 master 并未被更新!
git checkout -b foo o/master
git push
我们将一个并不叫 master 的分支上的工作推送到了远程仓库中的 master 分支上
设置远程追踪分支
另一种设置远程追踪分支的方法就是使用:git branch -u 命令
,执行:
git branch -u o/master foo
这样 foo 就会跟踪 o/master 了。如果当前就在 foo 分支上, 还可以省略 foo:
git branch -u o/master
git branch -u o/master foo
git commit
git pull --rebase
git push
posted on 2025-10-14 22:34 chuchengzhi 阅读(5) 评论(0) 收藏 举报