最近在网上有个真实发生的案例比较火,说的是一个新入职的员工,不会用 Git 拉代码,第二天被开除。由此,可见 Git 对我们工作的重要性,无论是前端后端,都是离不开 Git 的,下面就让我们一探究竟吧。
上面的案例引申出一个问题,入职一家新公司,你的 leader 给你分配了仓库的权限后,如何配置本地的 Git 环境并拉取代码?莫慌,按照下面我讲的四个步骤走,保证你可以顺利使用 Git 进行拉取代码!
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(读音为/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 的工作流程分为以下几步
添加文件到暂存区
# 添加某个文件到暂存区,后面可以跟多个文件,以空格区分
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.jsPlease 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 的使用技巧后,在日常工作中多多练习,相信会给你带来很大的收获!
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/bGOzidcKItcBmjD78uDlxw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。