Git的分支管理

版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:


每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。


当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:


你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:


假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:


所以Git合并分支也很快!就改改指针,工作区内容也不变!

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:



我们创建 dev 分支,然后切换到 dev 分支

$ git checkout -b dev
等价于
$ git branch dev
$ git checkout dev

查看当前所有分支
$ git branch

列出所有分支,当前分支前面会标一个*

$ git checkout master
可以做一个这样的实验:先Clone一个项目,创建一个新的分支dev,然后切换到dev分支,修改项目中的文件,add并且commit,再回到master分支。这个时候打开项目刚刚修改的文件会发现文件还原了。原因是修改只在分支dev中并提交,而master未变。

我们在master分支下合并dev分支

$ git merge dev
合并后修改的内容就出现了,这时可以删除dev分支

$ git branch -d dev

分支管理的一些BUG及特殊情况

在master分支和分支都有新的提交变成了这样:


这种情况下Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突

远程文件内容为:"and" master内容:"and 1" branch内容:"and 2"

例如:当修改了内容Git会自动提示我们当前master分支比远程的master分支要超前1个提交。会提示

CONFLICT (content): Merge conflict in xx.txt
Automatic merge failed; fix conflicts and then commit the result.
(注意,如果是在文件普通追加或者删除则是可以合并的)

Vim 命令打开文件,发现Git用<<<<<<<=======>>>>>>>标记出不同分支的内容,修改冲突的语句,这里冲突的是1和2,

vim + 文件名
打开冲突的文件,手动修改冲突内容,改为1或者2,删除其他不相关内容,:wq保存并退出vim,再次add和commit。

下图所示:


用带参数的 git log 也可以看到分支的合并情况:

$ git log --graph --pretty=oneline --abbrev-commit
最后,删除 分支:
$ git branch -d 分支名

合并分支时,默认情况下Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,我们可以使用--no-ff方式的git merge 会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

临时保持分支,在适当的时候恢复
这个方式类似于游戏里的存档,在打BOSS时,可以之前先存当前的信息,在之后可以任意的回到此刻。

比如在同一项目有一个紧急任务需要优先处理,而当前的内容可能不能马上commit,这个时候可以使用把工作现场git stash一下保存,在处理完优先的内容后git stash pop,回到工作现场。

恢复现场有两种,

一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;git stash list命令查看工作现场list

另一种方式是用git stash pop,恢复的同时把stash内容也删了

有时候后新增一个功能也需要新建一分支,但在没merge合并前功能因各种原因需要取消可以通过git branch -D <name>强行删除。

Git多人协作

当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin

要查看远程库的信息,用git remote或者,git remote -v显示更详细的信息

推送分支

$ git push origin master

如果要推送其他分支,比如dev,就改成
$ git push origin dev

抓取分支

如果远程的分支和本地的分支有冲突,推送至如github不成功, 先用 git pull获取最新的提交 然后,在本地合并,解决冲突再推送。
还有可能遇到以下两种情况:
1、在本地创建和远程分支对应的分支,使用 git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
2、建立本地分支和远程分支的关联,使用 git branch --set-upstream branch-name origin/branch-name

Git标签

Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。
  • 命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;

  • git tag -a <tagname> -m "blablabla..."可以指定标签信息;

  • git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;

  • 命令git tag可以查看所有标签。

  • 可以用git show <tagname>查看标签信息

  • 如果标签打错了,也可以删除,因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除

    $ git tag -d 标签名

  • 命令git push origin <tagname>推送标签到远程,或者全部标签推送远程

    $ git push origin --tags

  • 标签在远程的删除,需要先从本地删除然后从远程删除。

    $ git tag -d 标签名
    $ git push origin :refs/tags/标签名
    

    忽略特殊文件

  • 有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件

    所有配置文件可以直接在线浏览:https://github.com/github/gitignore

    忽略文件的原则是:

    1. 忽略操作系统自动生成的文件,比如缩略图等;
    2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
    3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

    举个例子:

    假设你在Windows下进行Python开发,Windows会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有Desktop.ini文件,因此你需要忽略Windows自动生成的垃圾文件:

    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini
    

    然后,继续忽略Python编译产生的.pyc.pyodist等文件或目录:

    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build
    

    加上你自己定义的文件,最终得到一个完整的.gitignore文件,内容如下:

    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini
    
    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build
    
    # My configurations:
    db.ini
    deploy_key_rsa
    

    最后一步就是把.gitignore也提交到Git,就完成了!当然检验.gitignore的标准是git status命令是不是说working directory clean

    Git的官方网站: http://git-scm.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值