Git Day.5 Branch(2)

2016-09-20  本文已影响0人  DendiSe7en

上海这些天开始有了秋天的感觉,在我没有更新博客的日子里,已经感冒了一次,所以今年的感冒次数已经用完了。烦人的工作也暂告一段落,最最重要的是,中秋来了。然而假期总是比平时上班还忙。远在棒子国的小伙伴也回到了祖国母亲的怀抱,简直开心(主要是看他被他爸妈嫌弃我开心)。今天的任务就是把分支这章结束掉,其实之前来来回回已经看过很多遍了。一直没有时间写下来。


1.查看分支:

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git branch -v #加上-v可以查看分支详情
iss53  19c769e iss53.txt
* master bd0cb0d [ahead 9] 
Merge branch 'iss53' Test about the merging between two branches
Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (testing)
$ git branch --merged#查看已合并分支
  iss53
  master
* testing
Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (testing)
$ git branch --no-merged#查看未合并分支

2.新建,切换分支:
  其实在上一篇已经有提到新建和切换,直接贴代码

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git branch testing#新建分支

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git checkout testing#切换到新建的分支testing
Switched to branch 'testing'

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git checkout -b testing#合并上面两步
Switched to a new branch 'testing'

3.删除分支:
  针对有未合并内容的,会有提醒

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git branch -d testing
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git branch -D testing
Deleted branch testing (was 272283b).

没有未合并内容的,可以直接删除

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moreTestAboutGit (master)
$ git branch -d testing
Deleted branch testing (was bd0cb0d).

"或者把它们想象成工作流水线,或许更好理解一些,经过测试的提交对象集合被遴选到更稳定的流水线"

关于这种使用这种模式的建议:
  "你可以用这招维护不同层次的稳定性。某些大项目还会有个 proposed(建议)或 pu(proposed updates,建议更新)分支,它包含着那些可能还没有成熟到进入 next或 master 的内容。
  这么做的目的是拥有不同层次的稳定性:当这些分支进入到更稳定的水平时,再把它们合并到更高层分支中去。再次说明下,使用多个长期分支的做法并非必需,不过一般来说,对于特大型项目或特复杂的项目,这么做确实更容易管理。"

(ProGit原文:经过重新分段)
    “现在我们来看一个实际的例子。请看下图 ,由下往上:
    1.起先我们在 master工作到 C1,然后开始一个新分支iss91 尝试修复 91 号缺陷,
    2.提交到 C6 的时候,又冒出一个解决该问题的新办法,
    3.于是从之前 C4 的地方又分出一个分支 iss91v2,
    4.干到 C8 的时候,又回到主干 master 中提交了 C9 和 C10,
    5.再回到 iss91v2 继续工作,提交 C11,
    6.接着,又冒出个不太确定的想法,从 master 的最新提交 C10 处开了个新的分支 dumbidea 做些试验。”

"现在,假定两件事情:我们最终决定使用第二个解决方案,即 iss91v2 中的办法;另外,我们把 dumbidea分支拿给同事们看了以后,发现它竟然是个天才之作。
    所以接下来,我们准备抛弃原来的 iss91分支(实际上会丢弃 C5 和 C6),直接在主干中并入另外两个分支。最终的提交历史将变成下图这样:"



这一章看了好几遍,却发现整篇都专注在远程分支的使用方式,连远程分支的查看都没提及:

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ git branch -a #查看远程分支
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master

不难发现,我们得到的结果里面,有一个HEAD 这个就是之前提及到的HEAD的指针,表示你当前所在的分支。

然后看下文档提供的例子:
  我们先从远程仓库,clone整个repos下来到我们本地,这时候git会在本地给我们自动创建一个名为origin的仓库 和master分支,当然你可以自定义仓库名。如图:

这时候你本地的项目怎么狂暴改都没关系,因为你不提交到远程分支就没有任何影响,而如果在你修改本地内容的这段时间,服务器上的分支如果有更新。那么在你提交的时候,需要你先从服务器上同步最新的内容到本地,然后再提交。
  官方的文档也直接是这样做的,但是我觉得我有必要去试下能不能直接提交。(下面是作死的内容,没有兴趣可以跳过,我只是为了证明如果不同步远程分支上的最新内容,就无法提交本地分支到远程分支上。)

首先,我在两个不同的目录clone同一个项目。分别是A和B。
  A目录:

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS
$ git clone git@github.com:DendiSe7enGitHub/moreTestAboutGit.git
Cloning into 'moreTestAboutGit'...
remote: Counting objects: 12, done.
remote: Total 12 (delta 0), reused 0 (delta 0), pack-reused 12
Receiving objects: 100% (12/12), done.
Resolving deltas: 100% (1/1), done.
Checking connectivity... done.

B目录:(这里出现这个提示是因为我B目录已经clone过这个项目了)

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH (master)
$ git clone git@github.com:DendiSe7enGitHub/moreTestAboutGit.git
fatal: destination path 'moreTestAboutGit' 
already exists and is not an empty     directory.

然后我在A目录,新建了一个文件(BranchTestFile.txt),然后push到远程分支master上

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS
$ cd moretestaboutgit# 进入到新clone的本地仓库目录

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ git branch -a#查看当前本地和远程分支
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ ls
gitignore  readme.md  READMORE

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ vim BranchTestFile.txt    #创建文件BranchTestFile.txt

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ git add BranchTestFile.txt
warning: LF will be replaced by CRLF in BranchTestFile.txt.
The file will have its original line endings in your working directory.

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ git commit -m"Test Branch"#提交到本地
[master adec571] Test Branch
 1 file changed, 1 insertion(+)
 create mode 100644 BranchTestFile.txt

Dendoink@QELRM4A8Y4JCC8E MINGW64 /d/GITREPOS/moretestaboutgit (master)
$ git push origin master#将本地的修改push到远程分支上
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 292 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local objects.
To github.com:DendiSe7enGitHub/moreTestAboutGit.git
   9f012bb..adec571  master -> master

这里有一点需要提一下,我用的git push origin master其实是简便的写法,完整的是:git push origin master:master 意思是,将本地master分支推送到远程仓库origin的master分支。
  然后现在远程分支master上,相对于我们之前clone的B分支来说,已经有了新的更新。也就是我刚刚通过A分支提交的代码。
  如果这时候我想要在B分支上也新建一个文件,然后提交到远程分支上,能提交么?试试看:

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH (master)
$ cd moretestaboutgit#进入新clone的仓库目录

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ vim testBranch2#创建一个文件 testBranch2

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git status#查看当前本地分支状态
On branch testing
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        testBranch2

nothing added to commit but untracked files present (use "git add" to track)

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git add testBranch2#将新添加的文件加到暂存区
warning: LF will be replaced by CRLF in testBranch2.
The file will have its original line endings in your working directory.

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git commit -m"Test Branch2"#提交更新到本地
[testing 41672ca] Test Branch2
 1 file changed, 1 insertion(+)
 create mode 100644 testBranch2

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git push origin master#将当前本地分支推送到master上
To github.com:DendiSe7enGitHub/moreTestAboutGit.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:DendiSe7enGitHub/moreTestAboutGit.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

不出意外的报错了。
  "Updates were rejected because the remote contains work that you do not have locally. This is usually caused by another repository pushing to the same ref. You may want to first integrate the remote changes (e.g., 'git pull ...') before pushing again. See the 'Note about fast-forwards' in 'git push --help' for details."
  "本次更新,因为远程分支包含你本地没有的工作项目而被拒绝。这通常由其他仓库提交的更新到同一个远程分支引起。你可能在再次推送之前,想要整合远程的改动。"
  然后解决的办法就是按照官方的文档说的,先fetch远程的分支数据到本地分支,再提交。

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git fetch origin
remote: Counting objects: 8, done.
remote: Total 8 (delta 2), reused 2 (delta 2), pack-reused 6
Unpacking objects: 100% (8/8), done.
From github.com:DendiSe7enGitHub/moreTestAboutGit
   7bd6f76..adec571  master     -> origin/master

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git push origin master
To github.com:DendiSe7enGitHub/moreTestAboutGit.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:DendiSe7enGitHub/moreTestA   boutGit.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

竟然还是报错?我仔细查了下,原来当前的工作分支并不是本地的master而是testing分支。

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git branch -v
  iss53   19c769e iss53.txt
  master  bd0cb0d [ahead 9, behind 3] Merge branch 'iss53' Test about the merging between two branches
* testing 35256d3 Merge branch 'master' of github.com:DendiSe7enGitHub/moreTestAboutGit into testing

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (testing)
$ git checkout master
Switched to branch 'master'
Your branch and 'origin/master' have diverged,
and have 9 and 3 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (master)
$ git pull origin master
From github.com:DendiSe7enGitHub/moreTestAboutGit
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 BranchTestFile.txt | 1 +
 readme.md          | 2 ++
 2 files changed, 3 insertions(+)
 create mode 100644 BranchTestFile.txt
 create mode 100644 readme.md

Dendoink@QELRM4A8Y4JCC8E MINGW64 /e/GITPUSH/moretestaboutgit (master)
$ git push origin master
Counting objects: 25, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (25/25), 2.35 KiB | 0 bytes/s, done.
Total 25 (delta 13), reused 0 (delta 0)
remote: Resolving deltas: 100% (13/13), completed with 1 local objects.

如果你是个细心的读者,肯定会发现我最后这次提交没有fetch 但是也提交成功了,而且我用了git pull这个命令。为什么呢,实际上 git pull 相当于 git fetch + git merge 然后我直接push 就成功了。到了这里其实才刚刚结束推送分支这块的内容。

作为一个推送者,我们的工作结束了,那如果我们是那个被动接收的人呢?面对一个新的分支,你有两种选择

(接下来这两段直接引用原文)
 2.跟踪远程分支
  从远程分支 checkout出来的本地分支,称为 跟踪分支 (tracking branch)。
  跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。
  同样,在这些分支里运行 git pull 会获取所远程索引,并把它们的数据都合并到本地分支中来。
  在克隆仓库时,Git 通常会自动创建一个名为 master 的分支来跟踪 origin/master。这正是 git push 和 git pull 一开始就能正常工作的原因。当然,你可以随心所欲地设定为其它跟踪分支:
  比如 origin 上除了 master之外的其它分支。刚才我们已经看到了这样的一个例子:git checkout -b [分支名] [远程名]/[分支名]。如果你有 1.6.2 以上版本的 Git,还可以用 --track 选项简化:

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

要为本地分支设定不同于远程分支的名字,只需在第一个版本的命令里换个名字:

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'

3.删除远程分支
  如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的 master分支(或任何其他存放稳定代码的分支),可以用这个非常无厘头的语法来删除它:git push [远程名] :[分支名]。如果想在服务器上删除serverfix 分支,运行下面的命令:

$ git push origin :serverfix
To git@github.com:schacon/simplegit.git 
- [deleted] serverfix

咚!服务器上的分支没了。你最好特别留心这一页,因为你一定会用到那个命令,而且你很可能会忘掉它的语法。有种方便记忆这条命令的方法:记住我们不久前见过的 git push [远程名] [本地分支]:[远程分支] 语法,如果省略 [本地分支],那就等于是在说“在这里提取空白然后把它变成[远程分支]”。


上一篇下一篇

猜你喜欢

热点阅读