这是第 103 篇不掺水的原创,想获取更多原创好文,请搜索公众号关注咱们吧~ 本文首发于政采云前端博客:我在工做中是如何使用 git 的html
最近在网上有个真实发生的案例比较火,说的是一个新入职的员工,不会用 Git 拉代码,次日被开除。由此,可见 Git 对咱们工做的重要性,不管是前端后端,都是离不开 Git 的,下面就让咱们一探究竟吧。前端
上面的案例引伸出一个问题,入职一家新公司,你的 leader 给你分配了仓库的权限后,如何配置本地的 Git 环境并拉取代码?莫慌,按照下面我讲的四个步骤走,保证你能够顺利使用 Git 进行拉取代码!ios
下载 Git 下载地址 ,选择本身系统对应的版本下载便可。git
在你的电脑上生成 ssh 秘钥,打开终端,执行 ssh-keygen -t rsa -C "你公司内部邮箱地址"
,若是执行成功,切换到 ~/.ssh
目录下,此时目录应该以下所示。复制 id_rsa.pub
的内容。程序员
这里以 Github 为例,以下图所示,进入 settings -> SSH and GPG keys
经过 cat
命令查看文件 id_rsa.pub
的内容,而后复制过来,点击 add ssh key
,这一步等于说把你的公钥放到了 Github 上进行托管。shell
全局配置 Git 的用户名和邮箱axios
git config --global user.name "xxx"
git config --global user.email "xxx@xx.com"
复制代码
完成以上四步,你就能够愉快 pull 代码开发了。和 https 拉取方式不一样的是,https 方式须要每次提交前都手动输入用户名和密码,ssh 的方式配置完毕后 Git 都会使用你本地的私钥和远程仓库的公钥进行验证是不是一对秘钥,从而简化了操做流程。vim
在介绍 Git 的相关操做前,我以为很是有必要了解 Git 的由来,以及 Git 是用来解决什么问题的。Git(读音为/gɪt/)是一个开源的分布式版本控制系统,能够有效、高速地处理从很小到很是大的项目版本管理。 Linus Torvalds ,这我的我相信你们都知道吧,开源 Linux 系统的发明人。现在,你看到的大部分服务器其实都是运行在 Linux 系统上,使人感到称叹的是,这位大神级别的程序员不只创造了 Linux 系统。那 Linux 的代码是如何管理的呢?2002年以前,世界各地的志愿者把源代码文件经过 diff 的方式发给 Linus,而后由 Linus 本人经过手工方式合并代码!要知道,当时的 Linux 的代码量已经很大了,经过人工管理的方式,一是容易出错,二是效率低。因而 Linus 选择了一个商业的版本控制系统 BitKeeper,BitKeeper 的东家 BitMover 公司出于人道主义精神,受权 Linux 社区无偿使用这个版本控制系统。最后,出于某种缘由,BitMover 公司收回了 Linux 社区的无偿使用权,因而 Linus 花了两周时间本身用 C 语言 写了一个分布式版本控制系统,这就是 Git 的由来了。后端
要想弄懂 Git 是怎么对咱们的代码进行管理的,那首当其冲的是了解 Git 的工做区域是如何构成的。由于,只有完全弄懂了 Git 工做区域的构成,你才能够在适当的区域使用合适的命令。以下图所示,此图包含了 Git 的4个工做区和一些常见的操做。缓存
Workspace:工做区,就是平时进行开发改动的地方,是当前看到最新的内容,在开发的过程也就是对工做区的操做
Index:暂存区,当执行 git add
的命令后,工做区的文件就会被移入暂存区,暂存区标记了当前工做区中那些内容是被 Git 管理的,当完成某个需求或者功能后须要提交代码,第一步就是经过 git add
先提交到暂存区。
Repository:本地仓库,位于本身的电脑上,经过 git commit
提交暂存区的内容,会进入本地仓库。
Remote:远程仓库,用来托管代码的服务器,远程仓库的内容可以被分布在多个地点的处于协做关系的本地仓库修改,本地仓库修改完代码后经过 git push
命令同步代码到远程仓库。
通常来讲,Git 的工做流程分为如下几步
1.在工做区开发,添加,修改文件。
2.将修改后的文件放入暂存区。
3.将暂存区域的文件提交到本地仓库。
4.将本地仓库的修改推送到远程仓库。
复制代码
添加文件到暂存区
# 添加某个文件到暂存区,后面能够跟多个文件,以空格区分
git add xxx
# 添加当前更改的全部文件到暂存区。
git add .
复制代码
# 提交暂存的更改,会新开编辑器进行编辑
git commit
# 提交暂存的更改,并记录下备注
git commit -m "you message"
# 等同于 git add . && git commit -m
git commit -am
# 对最近一次的提交的信息进行修改,此操做会修改commit的hash值
git commit --amend
复制代码
# 从远程仓库拉取代码并合并到本地,可简写为 git pull 等同于 git fetch && git merge
git pull <远程主机名> <远程分支名>:<本地分支名>
# 使用rebase的模式进行合并
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
复制代码
与 git pull
不一样的是 git fetch
操做仅仅只会拉取远程的更改,不会自动进行 merge 操做。对你当前的代码没有影响
# 获取远程仓库特定分支的更新
git fetch <远程主机名> <分支名>
# 获取远程仓库全部分支的更新
git fetch --all
复制代码
# 新建本地分支,但不切换
git branch <branch-name>
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 查看本地和远程分支
git branch -a
# 删除本地分支
git branch -D <branch-nane>
# 从新命名分支
git branch -m <old-branch-name> <new-branch-name>
复制代码
rebase 翻译为变基,他的做用和 merge 很类似,用于把一个分支的修改合并到当前分支上。
以下图所示,下图介绍了通过 rebase 后提交历史的变化状况。
如今咱们来用一个例子来解释一下上面的过程。
假设咱们如今有2条分支,一个为 master,一个为 feature/1,他们都基于初始的一个提交 add readme 进行检出分支,以后,master 分支增长了 3.js 和 4.js 的文件,分别进行了2次提交,feature/1 也增长了 1.js 和 2.js 的文件,分别对应如下2条提交记录。
此时,对应分支的提交记录以下。
master 分支以下图:
feature/1 分支以下图
结合起来看是这样的
此时,切换到 feature/1 分支下,执行 git rebase master
,成功以后,经过 git log
查看记录。
以下图所示:能够看到先是逐个应用了 mater 分支的更改,而后以 master 分支最后的提交做为基点,再逐个应用 feature/1 的每一个更改。
因此,咱们的提交记录就会很是清晰,没有分叉,上面演示的是比较顺利的状况,可是大部分状况下,rebase 的过程当中会产生冲突的,此时,就须要手动解决冲突,而后使用依次 git add
、git rebase --continue
的方式来处理冲突,完成 rebase 的过程,若是不想要某次 rebase 的结果,那么须要使用 git rebase --skip
来跳过此次 rebase 操做。
不一样于 git rebase
的是,git merge
在不是 fast-forward(快速合并)的状况下,会产生一条额外的合并记录,相似 Merge branch 'xxx' into 'xxx'
的一条提交信息。
另外,在解决冲突的时候,用 merge 只须要解决一次冲突便可,简单粗暴,而用 rebase 的时候 ,须要依次解决每次的冲突,才能够提交。
在开发中,常会遇到在一个分支上产生了不少的无效的提交,这种状况下使用 rebase 的交互式模式能够把已经发生的屡次提交压缩成一次提交,获得了一个干净的提交历史,例如某个分支的提交历史状况以下:
进入交互式模式的方式是执行:
git rebase -i <base-commit>
复制代码
参数 base-commit
就是指明操做的基点提交对象,基于这个基点进行 rebase 的操做,对于上述提交历史的例子,咱们要把最后的一个提交对象( ac18084 )以前的提交压缩成一次提交,咱们须要执行的命令格式是:
git rebase -i ac18084
复制代码
此时会进入一个 vim 的交互式页面,编辑器列出的信息像下列这样。
想要合并这一堆更改,咱们要使用 Squash 策略进行合并,即把当前的 commit 和它的上一个 commit 内容进行合并, 大概能够表示为下面这样,在交互模式的 rebase 下,至少保留一个 pick,不然命令会执行失败。
pick ... ...
s ... ...
s ... ...
s ... ...
复制代码
修改文件后 按下 :
而后 wq
保存退出,此时又会弹出一个编辑页面,这个页面是用来编辑提交的信息,修改成 feat: 更正
,最后保存一下,接着使用 git branch
查看提交的 commit 信息,rebase 后的提交记录以下图所示,是否是清爽了不少?rebase 操做可让咱们的提交历史变得更加清晰。
特别注意,只能在本身使用的 feature 分支上进行 rebase 操做,不容许在集成分支上进行 rebase,由于这种操做会修改集成分支的历史记录。
git cherry-pick
能够理解为”挑拣”提交,和 merge 合并一个分支的全部提交不一样的是,它会获取某一个分支的单笔提交,并做为一个新的提交引入到你当前分支上。当咱们须要在本地合入其余分支的提交时,若是咱们不想对整个分支进行合并,而是只想将某一次提交合入到本地当前分支上,那么就要使用 git cherry-pick
了。
以下场景,如下有三条分支,feature/cherry-pick1 和 feature/cherry-pick2 都是基于 master 检出的两条功能性分支,对应的分支 log 记录以下
master 分支的提交以下
如今 master 只须要 feature/cherry-pick1 和 feature/cherry-pick2 有关 change 的修改,并不关心有关 fix 内容的修改。此时就能够用 cherry-pick 指令了。
语法: git cherry-pick [commit-hash]
commit-hash 表示的是某次 commit 的 hash 值。如今,依次执行如下两条指令 git cherry-pick e0bb7f3
、git cherry-pick c9a3101
,过程当中,若是出现冲突,解决冲突后 进行 git add
,接着执行 git cherry-pick --continue
,最后,master 上的提交以下
此时,master 分支上应用了须要的提交,就达到了咱们想要的效果。若是须要多个 cherry-pick 须要同步到目标分支,能够简写为 git cherry-pick <first-commit-id>...<last-commit-id>
,这是一个左开右闭的区间,也就时说 first-commit-id
提交带来的代码的改动不会被合并过去,若是须要合并过去,可使用 git cherry-pick <first-commit-id>^...<last-commit-id>
,它表示包含 first-commit-id
到 last-commit-id
在内的提交都会被合并过去。
想象这么一个场景,你的项目最近有2个版本要上线,这两个版本还伴随着以前遗留的 bug 的修复,一开始的时候,你将 bug 修复在了第一个版本的 release 分支上,忽然在发版前一天,测试那边反馈,须要把第一个版本修复 bug 的内容改在第二个版本上,这个时候,第一个版本的集成分支的提交应该包括了第一个版本的功能内容,遗留 bug 修复的提交和其余同事提交的内容,想要经过 reset 的方式粗暴摘除以前的关于 bug 修复的 commit 确定是不行的,同时,这种作法比较危险,此时,咱们既不想破坏以前的提交记录,又想撤回咱们遗留 bug 的 commit 记录应该怎么作呢?git revert 就派上了用场。
git revert
撤销某次操做,此操做不会修改本来的提交记录,而是会新增一条提交记录来抵消某次操做。
语法: git revert <commit-id>
针对普通 commit
git revert <commit-id> -m
针对 merge 的 commit
下面就用一个案例来理解一下这个命令,以下图所示,假设被红框框起来的地方是会引发 bug 的一次提交,在他的提交以后,又进行了2次提交,其中包含了其它同事的提交。
此时想把引发提交的 bug 的干掉,执行 git revert 1121932
,执行操做后,再打开查看日志,以下图所示,能够看到是新增了一条 commit 记录,这个 commit 的产生的 msg 是自动生成的,Revert 开头,后面跟撤回的 commit-msg 信息 以前的 commit 记录并无消失,此时也达到了代码回退的效果
此外 git revert 也能够回滚屡次的提交
语法:git revert [commit-id1] [commit-id2] ...
注意这是一个前开后闭区间,即不包括 commit1 ,但包括 commit2 。
回滚咱们的提交有二种方式,一种是上文提到的git revert
命令外,还可使用 git reset
命令,那么它们二者有什么区别呢?
git revert
会新建一条 commit 信息,来撤回以前的修改。
git reset
会直接将提交记录退回到指定的 commit 上。
对于我的的 feature 分支而言,可使用 git reset
来回退历史记录,以后使用 git push --force
进行推送到远程,可是若是是在多人协做的集成分支上,不推荐直接使用 git reset
命令,而是使用更加安全的 git revert
命令进行撤回提交。这样,提交的历史记录不会被抹去,能够安全的进行撤回。
会有这么一个场景,如今你正在用你的 feature 分支上开发新功能。这时,生产环境上出现了一个 bug 须要紧急修复,可是你这部分代码还没开发完,不想提交,怎么办?这个时候能够用 git stash
命令先把工做区已经修改的文件暂存起来,而后切换到 hotfix 分支上进行 bug 的修复,修复完成后,切换回 feature 分支,从堆栈中恢复刚刚保存的内容。
基本命令以下
git stash //把本地的改动暂存起来
git stash save "message" 执行存储时,添加备注,方便查找。
git stash pop // 应用最近一次暂存的修改,并删除暂存的记录
git stash apply // 应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即 stash@{0},若是要使用其余个,git stash apply stash@{$num} 。
git stash list // 查看 stash 有哪些存储
git stash clear // 删除全部缓存的 stash
复制代码
下面经过几幅图对 stash 的命令作进一步了解。
此时,我正在开发一个新功能,修改了 1.js 文件里的内容
还没开发完成,这个时候,我想切换到 hotfix 分支上修复 bug,得暂停下开发切换到 hotfix 分支,可是如今工做区还有内容,此时若是切换分支 Git 会报出下面的错误
error: Your local changes to the following files would be overwritten by checkout:
1.js
Please commit your changes or stash them before you switch branches.
Aborting
复制代码
上面那句话的意思就是说工做区有文件修改,不能提交,须要先进行 commit 或者 stash 操做,执行 git stash
,结果以下
Saved working directory and index state WIP on stash: 22e561c feat: add 1.js
复制代码
此时,咱们的工做区已经干净了,能够切换到 hotfix 分支进行 bug 修复的工做,假设咱们如今 bug 修复完成了,继续切回 feature 分支进行本来功能的开发,此时只须要执行 git stash pop
,以前咱们暂存的修改就会恢复到工做区,以下图所示。
当咱们想要暂存文件,切换分支作某些事的时候,能够用 git stash
这种机制帮助开发。
推荐在使用 stash 的相关命令时,每一次暂存的时候,不要直接使用 git stash
命令进行暂存下来,而是使用 git stash save "message..."
这种方式,给本次的提交作一个信息的记录。这样,想应用更改的时候,先经过 git stash list
查看一下全部的暂存列表。以后,推荐使用 git stash apply stash@${num}
的方式进行应用对应的 stash,这样不会清空已有的 stash 的列表项,而且能应用到当前的工做区,不须要这个暂存的话,再手动清除就能够了。
开发中,咱们常常须要回退代码的操做,在不一样的工做区域中,回退代码的方式也是不相同的。以下图所示,假设如今要在 feature/revoke 分支上进行开发,
首先经过 git status
查看下如今的状态。
目前咱们的工做区是很干净的,没有任何修改的操做,此时,修改一下代码再次查看状态,能够看到,1.js 这个文件被修改了。
如今咱们想把 1.js 这个文件恢复到修改前的状态,即撤回工做区的修改,就可使用 git checkout -- <filename>
的命令,若是要撤回多个文件的修改,文件之间使用空格隔开,以下图所示,咱们撤回了 1.js 文件的修改,工做区也恢复干净了。
若是说如今咱们对文件进行了修改,而且已经提交到暂存区了,这部分文件咱们不想要的话,那么就能够经过 git reset <filename>
的命令来对特定的文件进行撤销,git reset
会撤回全部存在暂存区的文件,以下图所示,查看先后的状态可知,文件最后成功撤回到工做区了。
通常咱们在工做中,接到开发任务后,须要新建立一个分支进行开发 此时须要 用到 git branch
、git checkout
、 git pull
等命令,在咱们一顿操做后,开发完成,到了提交代码的阶段,又要诸如此类 git add
、git commit
、git push
等命令,虽然简单,可是输入起来也是不够简洁,做为一个程序员,开发程序就是为了提升咱们的效率的,懒是人类进步的源泉,因此咱们能够经过配置别名的方式,简化这些命令。
它的基本用法是 git config --global alias.<简化的字符> 原始命令
以下面的例子:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch
复制代码
这里将 co 表示 checkout,ci 表示 commit,br 表示 branch,之后提交就能够简写成
--global
是全局参数,也就是配置一次后,这些命令能够在这台电脑下的全部仓库都适用。这些命令实际上是更新你全局的 .gitconfig 文件,该文件用来保存全局的 git 配置,vim ~/.gitconfig
,执行这段命令后,显示以下,下图展现了刚才经过 git config --global alias
添加的 alias
。
除了上面那种直接经过命令的方式外,也能够经过修改这个文件的 alias
项来设置别名。
这里分享一个我本身经常使用的别名设置,把如下配置替换到 .gitconfig 文件里的 [alias]
所属的区域,而后就能够愉快的使用了~
[alias]
st = status -sb
co = checkout
br = branch
mg = merge
ci = commit
ds = diff --staged
dt = difftool
mt = mergetool
last = log -1 HEAD
latest = for-each-ref --sort=-committerdate --format=\"%(committername)@%(refname:short) [%(committerdate:short)] %(contents)\"
ls = log --pretty=format:\"%C(yellow)%h %C(blue)%ad %C(red)%d %C(reset)%s %C(green)[%cn]\" --decorate --date=short
hist = log --pretty=format:\"%C(yellow)%h %C(red)%d %C(reset)%s %C(green)[%an] %C(blue)%ad\" --topo-order --graph --date=short
type = cat-file -t
dump = cat-file -p
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
复制代码
这样,咱们每次想查看 Git 的历史记录,就不用输入那么一长串命令 直接使用 git lg
,下图是 axios 源码里的提交记录,使用封装后的 git lg
查看的效果图
分支之间的关系一眼就很明了,在哪一个 commit 上进行的 merge 操做也很清晰,能够帮助咱们很好的追溯历史的提交和解决问题。
本文由浅入深的的讲解了 Git 的环境搭建,基本用法,以及工做中使用较为高频的 Git 命令的用法,不管你是前端后端仍是其它端的开发,平常工做中少不了对 Git 的使用,咱们不只要会用,还要用的漂亮,用的灵活,用的稳健。这样才能在和同事协做项目的时候更加驾轻就熟,学会了本文这些 Git 的使用技巧后,在平常工做中多多练习,相信会给你带来很大的收获!
开源地址 www.zoo.team/openweekly/ (小报官网首页有微信交流群)
政采云前端团队(ZooTeam),一个年轻富有激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 40 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员构成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在平常的业务对接以外,还在物料体系、工程平台、搭建平台、性能体验、云端应用、数据分析及可视化等方向进行技术探索和实战,推进并落地了一系列的内部技术产品,持续探索前端技术体系的新边界。
若是你想改变一直被事折腾,但愿开始能折腾事;若是你想改变一直被告诫须要多些想法,却无从破局;若是你想改变你有能力去作成那个结果,却不须要你;若是你想改变你想作成的事须要一个团队去支撑,但没你带人的位置;若是你想改变既定的节奏,将会是“5 年工做时间 3 年工做经验”;若是你想改变原本悟性不错,但老是有那一层窗户纸的模糊… 若是你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的本身。若是你但愿参与到随着业务腾飞的过程,亲手推进一个有着深刻的业务理解、完善的技术体系、技术创造价值、影响力外溢的前端团队的成长历程,我以为咱们该聊聊。任什么时候间,等着你写点什么,发给 ZooTeam@cai-inc.com