目录

Git实用分享

概述

Git 对程序员来说太重要了,Git 不仅有些基础操作是必须要会的。

Git必知

Git进行版本控制的基础

  • 文件夹
  • 暂存区
  • 本地 git 文档库
  • 远程 git 文档库:远程 git 文档库其实可以完全和网络没有关系,「远程 git 文档库」可以和「本地 git 文档库」存在于同一台的计算机中。
/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs79jf351v414q395g1q7c1rfc1j.png

Git追踪文件的方式

  1. tracked: 被 tracked 的文件或者文件夹会被 git 追踪是否被修改
  2. ignored: ignored 状态是主动需要被忽略的,常见的就是 IDE 的一些文件
  3. untracked:一般是那种新建的文件或者子文件夹
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
On branch dev
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        target/AllPostPrediction.sh
        target/INFO
        target/assembly/
        target/bootstrap.sh
        target/classify/
        target/conf/
        target/pom.xml
        target/scalastyle-config.xml

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

其他

  1. commit: 相当于文档库的代码版本
  2. HEAD: HEAD 就是当前活跃分支的游标, 形象的记忆就是:你现在在哪儿,HEAD 就指向哪儿,所以 Git 才知道你在那儿
/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7jrj9g170pjlt1bh71mmo13p6a3.png

Git常用命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
git status / git add / git commit 
git branch/git checkout -b
git diff
git merge
git rebase
git stash
git log
git reset
git clone
git push
git fetch
git remote
fork

Git基础操作

以下是最基础的 git 操作命令, 新建一个文件, 然后检查以下文件夹内的情况, 在把新建的文件加入「暂存区」, 在把「暂存区」的文件提交到「本地 git 文档库」。

1
2
3
4
touch hello.txt
git status
git add -A
git commit -m "[add] add hello.txt"

使用git diff比较文件

git diff 的可以应用的场景比较多, 需要熟悉掌握。通过比较文件或者文件夹,可以找到自己修改过的地方。

1
2
3
4
5
# 比较不同 commit 节点的文件
git diff commit1 commit2

# 比较不同 branch 的文件
git diff master new

git merge和git rebase的区别

合并时候开发分支多了几个 commit 节点,但是 master 分支并没有任何改变,相当于将开发分支的文件内容 copy 一份到 master 分支上, master 分支会沿着开发分支"快进"到开发分支最新的节点, 特点是不产生新的 commit 节点,不会留下合并记录。 下图所示, 虽然两个分支重叠在一起,但是还是属于两个分支。

Fast-forward merge合并状态

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs77rd2u1k73guklkf1948g5e20.png

如果想留下合并记录可以使用 git merge –no-ff 分支名称, 这种方式又叫 3-way-merge。

merge之后留下了commit节点

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs785flhfr6bjd1ki61ka7142q9.png

表示将 master 和开发分支的最新 commit 节点的文件内容合并产生一个新的 commit 节点, 常见于 bug 分支和 master 分支同时有进行开发,git 会自动判断。

master同时也进行了开发

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs78bdlu2ro1hr0d6la3019u9m.png

当自己的开发分支和 master 分支同时在开发的时候,这种时候需要保持开发分支和 master 分支经常性的同步,才不至于在最后合并的阶段处理一堆的冲突。按之前说的可以不断的用 git merge 来实现。其实没什么问题,只是项目的commit节点演进图会变得很复杂。

不断的merge

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs78j93i199v18vv19bl12eh1ke09.png

rebase 则是把一个分支的修改应用到当前的分支,并且可以得到比较清晰的演进图。

通过rebase可以得到比较清晰的演进图

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs794sd37r01tpe66i185a1kid16.png

如果master分支的commit落后开发分支的commit太多,并且这些commit节点的冲突比较多,此时用rebase的话就要逐个冲突commit进行解决,因此这种情况推荐使用merge。

git stash的用法

git stash 是将正在修改的文件保存了一个快照, 此时是开辟了新的空间来暂存这些记录, git stash 其实包含了两个动作:

  • 存储文件夹中被git追踪的文件和文档库中最新文件版本的差异
  • 把文件夹中被git追踪的文件还原成文档库中最新的文件版本

git log查看commit记录

git log 可以用于查看 commit 的记录,所以要求有比较清楚的 commit message 是很重要的,这样再回退到某个 commit 是很方便的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
commit 07b77dafe3dff169670a7b875ab77919db94cdc2
Author: Oscar <runzhliu@163.com>
Date:   Wed Oct 11 22:58:25 2017 +0800

    [add] 增加REAMDE文件

commit 458746105297dbe834388a75dab735477173530e
Author: Oscar <runzhliu@163.com>
Date:   Wed Oct 11 22:25:09 2017 +0800

    [add] 增加gitignore

commit 5b7bcbdaa79cd0ea8e65909c44a44e9605806a2b
Author: Oscar <runzhliu@163.com>
Date:   Wed Oct 11 21:46:53 2017 +0800

    第四次提交

commit 0f239a7d51c6b0b1ee182adeff88d506a22b8128
Author: Oscar <runzhliu@163.com>
Date:   Tue Oct 10 23:40:03 2017 +0800

    第三次提交

commit ac9dc4b1bdee3cfc8bdf586cd0a040240c94de01
Author: Oscar <runzhliu@163.com>
Date:   Tue Oct 10 22:37:39 2017 +0800

    更改文件

commit bd4110d2640898b288b073e6c876bdd10dfc9055
Author: Oscar <runzhliu@Oscars-MacBook-Pro.local>
Date:   Tue Oct 10 22:34:25 2017 +0800

    首次commit

关于 commit 的 message 的书写的规范, 希望大家遵守

1
2
3
4
[add] 针对新增的文件或者功能
[update] 针对更改的文件或功能
[delete] 针对删除的文件或者功能
[fix] 针对修复的文件或者功能

回退的几个操作

git 有很好的回退机制, git resetgit checkoutgit revert 是你的 Git 工具箱中最有用的一些命令。它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用于特定文件。

git reset: 在提交层面上,reset 将一个分支的末端指向另一个提交。这可以用来移除当前分支的一些提交。比如,下面这两条命令让 hotfix 分支向后回退了两个提交。

1
2
git checkout hotfix
git reset HEAD~2
/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7ajmbr1jru70bhuf1goncd34n.png

git checkout

1
git checkout HEAD~2
/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7aobgsnvoalur0bujs19o054.png

git revert

Revert 撤销一个提交的同时会创建一个新的提交。这是一个安全的方法,因为它不会重写提交历史。比如,下面的命令会找出倒数第二个提交,然后创建一个新的提交来撤销这些更改,然后把这个提交加入项目中。

1
2
git checkout hotfix
git revert HEAD~2
/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7aqgn117kf1eti1h487411erv5h.png

操作远程git文档库

创建远程git文档库

可以在本地创建也可以在GitLab上直接创建

本地git文档库与远程git文档库的数据同步

git pull 拉代码 是为了使本地的远程 git 文档库的分支和远程 git 文档库的最新状态一致 其实是分了两个步骤,先是 git fetch 接着再使用 git merge,当然 merge 会使演进图比较复杂 也可以采用 rebase 为第二个步骤, git pull -r

git push 推代码 将本地的远程 git 文档库的代码推到远程 git 文档库 git push –set-upstream orgin 分支名称 可以设置本地git文档库的分支和远程git文档库的分支对应的关系 git remote -v 可以查看一下对应关系

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7hkf3s9ijeqjehl148n1u2i99.png

Git协作的方式

集中式工作流

持续在 master 上进行开发, 所有修改提交到这个分支上。本工作流只用到 master 这一个分支。

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7fvkarl4s6uv2op18j910hb75.png

功能分支工作流

根据开发的功能从 master 上切出新的分支进行开发, 功能开发隔离也让 pull requests 工作流成功可能, pull requests 工作流能为每个分支发起一个讨论, 在分支合入正式项目之前, 给其它开发者有表示赞同的机会。

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7h7nahutnlvnu1av5db58s.png

Gitflow工作流

Gitflow 工作流通过为功能开发、发布准备和维护分配独立的分支,让发布迭代过程更流畅

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7g7dk719s61pkvje1btc1r8t8f.png

Forking工作流

Fork的翻译可以是叉子或者是分支, 在Git系统里显然翻译成分支分叉是更合理的, 那么这样fork与branch又很像, fork是针对真个git文档库,而branch操作的对象是程序项目, 另外fork又和clone很像,因为都是操作文档库, 但是clone出来的文档库不会记录这个文档库的来源的, 而fork出来的文档库,会保留它的来源git文档库,将来这个fork得到的git文档库可以再合并到原来的git文档库, 然而fork操作如果离开了网络是不存在的,因为不是git程序原生的操作模式。

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7ia8k26h4jtqqsbjd91chk9m.png

Forking 工作流是分布式工作流,充分利用了 Git, 在分支和克隆上的优势。可以安全可靠地管理大团队的开发者 developer,并能接受不信任贡献者 contributor 的提交。

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7g1hus1vhj12pk155l12ghq547i.png

Git alias设置

  1. 配置oh-my-zsh
  2. 查看alias
  3. 自定义
1
2
3
4
5
6
7
# git 的 alias 设置
git config alias.gt 'status'
git gt
git config --unset alias.gt

# bash_profile 的 alias 设置
alias gamsg="git add --all && git commit -m"

Git实战

合理的切出分支进行开发

git-sharing 里面需要增加一个文件 first.txt

1
2
git checkout -b new
vim first.txt

开发新功能过程中要修bug

git-sharing 正在编辑一个文件 second.txt,然而被 pm 要求紧急删除 first.txt 文件的最后一行

1
git stash

几种常见的工作流的演示

Gitlab功能

观察commit演进图

这个演进图是远程文档库的演进图, 和本地文档库的演进图是不一样的

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs79tqgm1m6cf1vm5ne9lape3t.png

compare功能代替git diff

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs79vevb15rd1ppe4rc802khj4a.png

merge request的设置

由于是跟远程 master 分支进行合并, 所以请书写规范的 merge request 的信息, 方便 code review 以及问题的回溯。

/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs7eobbc1q8nuu5j66gp11sqc5u.png

Git Tips

  1. 仔细阅读git的错误提示
  2. 尽量使用命令行的操作方式, 减少 IDE 的依赖
  3. 多用git rm, 少用 rm a.txt | git add -A . 后者有丢代码的风险
  4. 多用 revert, 少用 git reset — hard, document/index/repository 级别
  5. 多久 commit 一次? 按功能来决定
  6. 经常性地和 master 做 rebase
/git%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/image_1bs76ia55ep81j191vv31112m8116.png

参考资料

  1. UdaCity-UD775
  2. Git Help
警告
本文最后更新于 2017年2月1日,文中内容可能已过时,请谨慎参考。