branch

2018-02-23  本文已影响0人  一江碎月

概念

何为分支

Git 中的分支,其实本质上仅仅是一个指向提交结点的可变指针。它会在每次提交之后自动往前移动。

假设原来的提交过程如下:


当新建一个 iss53 分支后,其结果如下:

可以看出,iss53 与 master 指向的是同一个提交结点。但 iss53 却是一个新的分支。


HEAD

Git 保存着一个名为 HEAD 的特别指针,它是一个指向你正在工作中的本地分支的指针(将 HEAD 想象为当前分支的别名)。它会在每次提交之后自动往前移动。也就是说,HEAD 表示当前分支

  1. HEAD~ 表示 HEAD 的父结点

  2. HEAD~2 表示 HEAD 的爷爷结点。可能通过修改 ~ 后的数字指向 HEAD 的哪一个祖先结点。

  3. 与 HEAD 相关的文件是 .git/HEAD 文件。

$ cat .git/HEAD
ref: refs/heads/master
$ git checkout dev
Switched to branch 'dev'
$ cat .git/HEAD 
ref: refs/heads/dev

可以发现,当切换分支后,HEAD 引用的文件位置已经发生了变化。

每新建一个分支,就会在 refs/heads/ 目录下以分支名新建一个文件。该文件存储的是当前分支最后一次提交的 SHA-1 值。


常用操作

文档

分支的操作有:新建、删除、查看、切换、合并、推送新分支到远程仓库、删除远程仓库分支、拉取远程仓库分支。

命令 含义
git branch <name> 创建新的分支
git branch <name> <checksum> 在指定的提交结点处创建新的分支
git checkout -b <name> 创建新的分支并切换到新分支
git checkout -b <name> <checksum> 在指定的提交结点处创建新的分支并切换到新分支
git checkout -B <name> 创建新的分支并切换到新分支。该命令会覆盖已有的同名分支
git branch -d <name> 删除指定的本地分支
git branch 查看本地所有分支
git branch -vv 列出本地分支及跟踪的远程分支,并展示两者差异
git branch -a 查看本地和远程仓库的分支。该操作不会进行网络请求
git checkout <name> 切换到指定的分支
git merge <name> 将指定的分支合并到当前分支
git push <别名> <local>:<remote> 将本地 local 分支推送到远程 remote 分支上
git push <别名> :<remote> 删除远程 remote 分支
git push <别名> --delete <remote> 删除远程 remote 分支
git pull <别名> <remote>:<local> 将远程的 remote 分支拉到本地的 local 分支上,如果没有,则新建 local 分支。同时,会进行合并操作
git fetch <别名> <remote>:<local> 将远程的 remote 分支拉到本地的 local 分支上,如果没有,则新建 local 分支

在指定的提交结点处创建分支时,提交结点可以是 tag,checksum,某个分支名等。因为这些数据都指向了一个提交结点。

跟远程仓库相关的操作,必须通过 push <别名> 将操作推送到仓库中。


新建

新建本地分支

命令 含义
git branch <name> 创建新的分支
git checkout -b <name> 创建新的分支并切换到新分支
git checkout -B <name> 创建新的分支并切换到新分支

新建的分支会将旧分支所有内容都复制一份。包括非暂存和非提交的

使用 branch 与 checkout 使用 主要区别在于:后者会切换到新建的分支,而前者不会。
使用 -b 与使用 -B 的主要区别在于:如果已存在同名分支,则 -b 会创建失败。而 -B 会强制新建分支,并使用新建分支覆盖旧分支。

$ git checkout -b test

它相当于依次执行下面两个命令:

$ git branch test
$ git checkout test

即先通过 branch <name> 创建一个新的分支,然后通过 checkout 切换到指定的分支。

新建远程分支

使用 git push <别名> <local>:<remote> 将本地分支推送到远程仓库不存在的分支上,远程仓库会自动创建新的分支。

其中 local 指的是本地分支名。remote 指的是远程仓库的分支名。如果省略 local ,则表示删除远程仓库 remote 分支。


删除

删除本地分支

通过 git branch [-d|--delete] <name> 删除指定的分支。

删除时,可以使用 -d 也可以使用 --delete 选项。

$ git branch 
* dev
  master
  test
$ git branch --delete test
Deleted branch test (was fe9eba5).
$ git branch
* dev
  master

删除远程分支

有两种实现方式:一种通过 --delete 命令指定删除的远程分支;一种通过省略本地分支名。

如:

$ git push demo2 :web5
To https://github.com/birdandcliff/gitdemo.git
 - [deleted]         web5

$ git push demo2 --delete web6
To https://github.com/birdandcliff/gitdemo.git
 - [deleted]         web6

第一种是通过省略本地分支名,删除远程分支 web5。
第二种通过直接使用 --delete 命令,删除远程分支 web6。


查看

  1. git branch 查看所有本地分支。分支名前有 * 的表示当前分支。
选项 含义
-a 查看本地分支与远程分支
-v 查看各个分支最后一个提交对象的信息
--merged 查看所有已合并到当前分支中的分支,已删除的不会出现
--no-merged 查看尚未合并到当前分支中的分支,已删除的不会出现

如:

$ git branch -a
* dev
  master
  remotes/demo2/dev

第三个为远程分支(本地没有)。如果不加 -a 选项,则只会出现前两个。第一个分支前面有 * ,表示当前的分支为 dev。

一般来说,--merged 列表中没有 * 的分支通常都可以用 git branch -d 来删掉,因为已经把它们合并到其他分支,删掉也没有任何影响。


切换

通过 git checkout <name> 切换到指定分支。

$ git checkout master
Switched to branch 'master'

后跟 -b 选项时,表示新建分支,并切换到新分支中。


合并

通过 git merge <name> 将指定的分支合并到当前分支中。

合并时,被合并的分支指向的提交结点不会发生变化,合并到的分支指向会发生变化。

合并时,如果产生冲突,需要手动解决冲突后再次 commit 才算合并完成。

$ git merge test
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

$ git status
On branch dev
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:   a.txt

no changes added to commit (use "git add" and/or "git commit -a")

上述分支进行合并时,产生了冲突。所以,需要手动解决冲突,并将结果进行 commit 。

产生冲突后,可以通过 git status 查看冲突时的状态,而且所有的冲突文件都列在 Unmerged paths 下。

问题

在合并时,可能会遇到如下错误提示:

$ git merge test
warning: refname 'test' is ambiguous.
Already up-to-date.

提示说 test 这个名字无法识别,这是因为有可能存在一个叫 test 的 tag,删除掉该 tag 后再进行合并即可。


拉取

  1. 通过 git pull <别名> <remote>:<local> 将远程的分支拉取到本地。如果本地不存在对应的分支,则新建。同时,会将远程分支内容进行合并。

    $ git pull origin web7:webaa
    remote: Counting objects: 3, done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
    Unpacking objects: 100% (3/3), done.
    From https://github.com/birdandcliff/gitdemo
     * [new branch]      web7       -> webaa
       7a6c13b..bf9ce37  web7       -> origin/web7
    Updating 7a6c13b..bf9ce37
    Fast-forward
     a.txt | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
  2. 通过 git fetch <别名> <remote>:<local> 将远程分支拉取到本地。

    $ git fetch origin web7
    From https://github.com/birdandcliff/gitdemo
     * branch            web7       -> FETCH_HEAD
    
  3. pull 与 fetch 的主要区别在于: pull = fetch + merge。使用 pull 时,不但将远程分支的内容拉取到本地,同时会将远程分支的内容与当前分支进行合并。但使用 fetch 就只是将远程分支内容拉取到本地,不会合并到当前分支中。

上一篇 下一篇

猜你喜欢

热点阅读