乐趣区

关于前端:我在工作中是如何使用-git-的

这是第 103 篇不掺水的原创,想获取更多原创好文,请搜寻公众号关注咱们吧~ 本文首发于政采云前端博客:我在工作中是如何应用 git 的

前言

最近在网上有个实在产生的案例比拟火,说的是一个新入职的员工,不会用 Git 拉代码,第二天被开革。由此,可见 Git 对咱们工作的重要性,无论是前端后端,都是离不开 Git 的,上面就让咱们一探到底吧。

下面的案例引申出一个问题,入职一家新公司,你的 leader 给你调配了仓库的权限后,如何配置本地的 Git 环境并拉取代码?莫慌,依照上面我讲的四个步骤走,保障你能够顺利应用 Git 进行拉取代码!

  1. 下载 Git 下载地址,抉择本人零碎对应的版本下载即可。
  2. 在你的电脑上生成 ssh 秘钥,关上终端,执行 ssh-keygen -t rsa -C "你公司外部邮箱地址",如果执行胜利,切换到 ~/.ssh 目录下,此时目录应该如下所示。复制 id_rsa.pub 的内容。

  3. 这里以 Github 为例,如下图所示,进入 settings -> SSH and GPG keys 通过 cat 命令查看文件 id_rsa.pub 的内容,而后复制过去,点击 add ssh key,这一步等于说把你的公钥放到了 Github 上进行托管。

  4. 全局配置 Git 的用户名和邮箱
git config --global user.name "xxx"
git config --global user.email "xxx@xx.com"

实现以上四步,你就能够欢快 pull 代码开发了。和 https 拉取形式不同的是,https 形式须要每次提交前都手动输出用户名和明码,ssh 的形式配置结束后 Git 都会应用你本地的私钥和近程仓库的公钥进行验证是否是一对秘钥,从而简化了操作流程。

Git 简介

在介绍 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 工作区域的形成,你才能够在适当的区域应用适合的命令。如下图所示,此图蕴含了 Git 的 4 个工作区和一些常见的操作。

Workspace:工作区,就是平时进行开发改变的中央,是以后看到最新的内容,在开发的过程也就是对工作区的操作

Index:暂存区,当执行 git add 的命令后,工作区的文件就会被移入暂存区,暂存区标记了当前工作区中那些内容是被 Git 治理的,当实现某个需要或者性能后须要提交代码,第一步就是通过 git add 先提交到暂存区。

Repository:本地仓库,位于本人的电脑上,通过 git commit 提交暂存区的内容,会进入本地仓库。

Remote:近程仓库,用来托管代码的服务器,近程仓库的内容可能被散布在多个地点的处于协作关系的本地仓库批改,本地仓库批改完代码后通过 git push 命令同步代码到近程仓库。

一般来说,Git 的工作流程分为以下几步

1. 在工作区开发,增加,批改文件。2. 将批改后的文件放入暂存区。3. 将暂存区域的文件提交到本地仓库。4. 将本地仓库的批改推送到近程仓库。

Git 基本操作

git add

增加文件到暂存区

# 增加某个文件到暂存区,前面能够跟多个文件,以空格辨别
git add xxx
# 增加以后更改的所有文件到暂存区。git add .

git commit

# 提交暂存的更改,会新开编辑器进行编辑
git commit 
# 提交暂存的更改,并记录下备注
git commit -m "you message"
# 等同于 git add . && git commit -m
git commit -am
# 对最近一次的提交的信息进行批改, 此操作会批改 commit 的 hash 值
git commit --amend

git pull

# 从近程仓库拉取代码并合并到本地,可简写为 git pull 等同于 git fetch && git merge 
git pull < 近程主机名 > < 近程分支名 >:< 本地分支名 >
# 应用 rebase 的模式进行合并
git pull --rebase < 近程主机名 > < 近程分支名 >:< 本地分支名 >

git fetch

git pull 不同的是 git fetch 操作仅仅只会拉取近程的更改,不会主动进行 merge 操作。对你以后的代码没有影响

# 获取近程仓库特定分支的更新
git fetch < 近程主机名 > < 分支名 >
# 获取近程仓库所有分支的更新
git fetch --all

git branch

# 新建本地分支,但不切换
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>

工作中应用 Git 解决问题的场景

git rebase 让你的提交记录更加清晰可读

git rebase 的应用

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 merge 和 git rebase 的区别

不同于 git rebase 的是,git merge 在不是 fast-forward(疾速合并)的状况下,会产生一条额定的合并记录,相似 Merge branch 'xxx' into 'xxx' 的一条提交信息。

另外,在解决抵触的时候,用 merge 只须要解决一次抵触即可,简略粗犷,而用 rebase 的时候,须要顺次解决每次的抵触,才能够提交。

git 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 获取指定的 commit

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 e0bb7f3git 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-idlast-commit-id 在内的提交都会被合并过来。

应用 git revert 回滚某次的提交

设想这么一个场景,你的我的项目最近有 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 命令进行撤回提交。这样,提交的历史记录不会被抹去,能够平安的进行撤回。

应用 git stash 来暂存文件

会有这么一个场景,当初你正在用你的 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 alias 晋升工作效率

个别咱们在工作中,接到开发工作后,须要新创建一个分支进行开发 此时须要 用到 git branchgit checkoutgit pull 等命令,在咱们一顿操作后,开发实现,到了提交代码的阶段,又要诸如此类 git addgit commitgit 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 的应用技巧后,在日常工作中多多练习,置信会给你带来很大的播种!

参考文献

阮一峰的 git 教程

Git merge 和 rebase 分支合并命令的区别

开源作品

  • 政采云前端小报

开源地址 www.zoo.team/openweekly/ (小报官网首页有微信交换群)

招贤纳士

政采云前端团队(ZooTeam),一个年老富裕激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 40 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员形成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在日常的业务对接之外,还在物料体系、工程平台、搭建平台、性能体验、云端利用、数据分析及可视化等方向进行技术摸索和实战,推动并落地了一系列的外部技术产品,继续摸索前端技术体系的新边界。

如果你想扭转始终被事折腾,心愿开始能折腾事;如果你想扭转始终被告诫须要多些想法,却无从破局;如果你想扭转你有能力去做成那个后果,却不须要你;如果你想扭转你想做成的事须要一个团队去撑持,但没你带人的地位;如果你想扭转既定的节奏,将会是“5 年工作工夫 3 年工作教训”;如果你想扭转原本悟性不错,但总是有那一层窗户纸的含糊… 如果你置信置信的力量,置信平凡人能成就不凡事,置信能遇到更好的本人。如果你心愿参加到随着业务腾飞的过程,亲手推动一个有着深刻的业务了解、欠缺的技术体系、技术发明价值、影响力外溢的前端团队的成长历程,我感觉咱们该聊聊。任何工夫,等着你写点什么,发给 ZooTeam@cai-inc.com

退出移动版