面试官:你知道git xx 和git xx的区别吗?看完这篇Git指南后直呼:内行!

「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!前端

前言

做为一名工程师,既然想要加入一个团队,并肩做战地协同开发项目,就必不可少要学会Git基本操做。面试过程当中,面试官不止是考察1-3年的工程师,高级岗位也一样会考察团队协做的能力。相信小伙伴们常常会在面试中被问到如下问题吧,能够帮助你测试一下你的Git基础牢不牢固。git

  • 代码开发到一半,须要紧急切换分支修复线上问题,该怎么办?
  • 代码合并有几种模式?分别有什么优缺点?
  • git fetchgit pull有什么区别,有合并操做吗?
  • git mergegit rebase有什么区别,它们的应用场景有哪些?
  • git resetgit revert有什么区别,该如何选择,回滚后的<commit-id>还能找到吗?

若是你心中已有答案,那么能够选择跳过这篇文章啦,愉快地继续摸鱼~github

若是你对这些概念还有些模糊,或者没有实际操做过,那么就须要好好阅读本篇文章啦!面试

接下来立刻进入正文啦,本文分四个部分介绍,你们能够自由选择阅读。后端

  • Git的区域示例图,帮助你们理解Git的结构。
  • Git的基本使用场景,介绍一些经常使用git命令。
  • Git的进阶使用场景,介绍一些高频出现的面试题目以及应用场景。
  • 最后介绍Git的下载地址、基本配置和工具推荐。

Git的区域

画了一个简单的示意图,供你们参考缓存

yuque_diagram.jpg

  • 远程仓库(Remote):在远程用于存放代码的服务器,远程仓库的内容可以被分布其余地方的本地仓库修改。
  • 本地仓库(Repository):在本身电脑上的仓库,平时咱们用git commit 提交到暂存区,就会存入本地仓库。
  • 暂存区(Index):执行 git add 后,工做区的文件就会被移入暂存区,表示哪些文件准备被提交,当完成某个功能后须要提交代码,能够经过 git add 先提交到暂存区。
  • 工做区(Workspace):工做区,开发过程当中,平时打代码的地方,看到是当前最新的修改内容。

Git的基本使用场景

如下命令远程主机名默认为origin,若是有其余远程主机,将origin替换为其余便可。bash

git fetch

# 获取远程仓库特定分支的更新
git fetch origin <分支名>

# 获取远程仓库全部分支的更新
git fetch --all
复制代码

git pull

# 从远程仓库拉取代码,并合并到本地,至关于 git fetch && git merge 
git pull origin <远程分支名>:<本地分支名>

# 拉取后,使用rebase的模式进行合并
git pull --rebase origin <远程分支名>:<本地分支名>
复制代码

注意服务器

  • 直接git pull 不加任何选项,等价于git fetch + git merge FETCH_HEAD,执行效果就是会拉取全部分支信息回来,可是只合并当前分支的更改。其余分支的变动没有执行合并。
  • 使用git pull --rebase 能够减小冲突的提交点,好比我本地已经提交,可是远程其余同事也有新的代码提交记录,此时拉取远端其余同事的代码,若是是merge的形式,就会有一个merge的commit记录。若是用rebase,就不会产生该合并记录,是将咱们的提交点挪到其余同事的提交点以后。

git branch

# 基于当前分支,新建一个本地分支,但不切换
git branch <branch-name> 

# 查看本地分支
git branch

# 查看远程分支
git branch -r

# 查看本地和远程分支
git branch -a

# 删除本地分支
git branch -D <branch-name>

# 基于旧分支建立一个新分支
git branch <new-branch-name> <old-branch-name> 

# 基于某提交点建立一个新分支
git branch <new-branch-name> <commit-id> 

# 从新命名分支
git branch -m <old-branch-name> <new-branch-name>
复制代码

git checkout

# 切换到某个分支上
git checkout <branch-name>

# 基于当前分支,建立一个分支并切换到新分支上
git checkout -b <branch-name>
复制代码

git add

# 添把当前工做区修改的文件添加到暂存区,多个文件能够用空格隔开
git add xxx

# 添加当前工做区修改的全部文件到暂存区
git add .
复制代码

git commit

# 提交暂存区中的全部文件,并写下提交的概要信息
git commit -m "message"

# 相等于 git add . && git commit -m
git commit -am

# 对最近一次的提交的信息进行修改,此操做会修改commit的hash值
git commit --amend
复制代码

git push

# 推送提交到远程仓库
git push 

# 强行推送到远程仓库
git push -f
复制代码

git tag

# 查看全部已打上的标签
git tag 

# 新增一个标签打在当前提交点上,并写上标签信息
git tag -a <version> -m 'message' 

# 为指定提交点打上标签
git tag -a <version> <commit-id> 

# 删除指定标签
git tag -d <version> 
复制代码

Git的进阶使用场景

HEAD表示最新提交 ;HEAD^表示上一次; HEAD~n表示第n次(从0开始,表示最近一次)markdown

正常协做

  • git pull 拉取远程仓库的最新代码
  • 工做区修改代码,完成功能开发
  • git add . 添加修改的文件到暂存区
  • git commit -m 'message' 提交到本地仓库
  • git push将本地仓库的修改推送到远程仓库

代码合并

git merge

自动建立一个新的合并提交点merge-commit,且包含两个分支记录。若是合并的时候遇到冲突,仅须要修改解决冲突后,从新commit。app

  • 场景:如dev要合并进主分支master,保留详细的合并信息
  • 优势:展现真实的commit状况
  • 缺点:分支杂乱
git checkout master
git merge dev
复制代码

rf1o2b6eduboqwkigg3w.gif

git merge 的几种模式

  • git merge --ff (默认--ff,fast-farward)
    • 结果:被merge的分支和当前分支在图形上并为一条线,被merge的提交点commit合并到当前分支,没有新的提交点merge
    • 缺点:代码合并不冲突时,默认快速合并,主分支按时间顺序混入其余分支的零碎commit点。并且删除分支,会丢失分支信息。
  • git merge --no-ff(不快速合并、推荐)
    • 结果:被merge的分支和当前分支不在一条线上,被merge的提交点commit还在原来的分支上,并在当前分支产生一个新提交点merge
    • 优势:代码合并产生冲突就会走这个模式,利于回滚整个大版本(主分支本身的commit点)
  • git merge --squash(把屡次分支commit历史压缩为一次)
    • 结果:把屡次分支commit历史压缩为一次

image.png

git rebase

  • 不产生merge commit,变换起始点位置,“整理”成一条直线,且能使用命令合并屡次commit。
  • 如在develop上git rebase master 就会拉取到master上的最新代码合并进来,也就是将分支的起始时间指向master上最新的commit上。自动保留的最新近的修改,不会遇到合并冲突。并且可交互操做(执行合并删除commit),可经过交互式变基来合并分支以前的commit历史git rebase -i HEAD~3
  • 场景:主要发生在我的分支上,如 git rebase master整理本身的dev变成一条线。频繁进行了git commit提交,可用交互操做drop删除一些提交,squash提交融合前一个提交中。
  • 优势:简洁的提交历史
  • 缺点:发生错误难定位,解决冲突比较繁琐,要一个一个解决。
git checkout dev
git rebase master
复制代码

dwyukhq8yj2xliq4i50e.gifmsofpv7k6rcmpaaefscm.gif

git merge和git rebase的区别

  • merge会保留两个分支的commit信息,并且是交叉着的,即便是ff模式,两个分支的commit信息会混合在一块儿(按真实提交时间排序),多用于本身dev合并进master。
  • rebase意思是变基,改变分支的起始位置,在dev上git rebase master,将dev的屡次commit一块儿拉到要master最新提交的后面(时间最新),变成一条线,多用于整理本身的dev提交历史,而后把master最新代码合进来。
  • 使用rebase仍是merge更多的是管理风格的问题,有个较好实践:
    • 就是dev在merge进主分支(如master)以前,最好将本身的dev分支给rebase到最新的主分支(如master)上,而后用pull request建立普通merge请求。
    • 用rebase整理成重写commit历史,全部修改拉到master的最新修改前面,保证dev运行在当前最新的主branch的代码。避免了git历史提交里无心义的交织。
  • 假设场景:从 dev 拉出分支 feature-a。
    • 那么当 dev 要合并 feature-a 的内容时,使用 git merge feature-a
    • 反过来当 feature-a 要更新 dev 的内容时,使用 git rebase dev
  • git merge和git rebase 二者对比图
    • git merge图示 image.png
    • git rebase图示 image.png

取消合并

# 取消merge合并
git merge --abort
# 取消rebase合并
git rebase --abort
复制代码

代码回退

代码回退的几种方式

  • git checkout
  • git reset
    • --hard:硬重置,影响【工做区、暂存区、本地仓库】
    • --mixed:默认,影响【暂存区、本地仓库】,被重置的修改内容还留在工做区
    • --soft:软重置,影响 【本地仓库】,被重置的修改内容还留在工做区和暂存区
  • git revert
# 撤回工做区该文件的修改,多个文件用空格隔开
git checkout -- <file-name>
# 撤回工做区全部改动
git checkout .

# 放弃已git add到暂存区的指定文件的缓存(HEAD表示最新版本)
git reset HEAD <file-name>
# 放弃全部的缓存
git reset HEAD .
# 丢弃已commit的其余版本,hard参数表示同时重置工做区的修改
git reset --hard <commit-id>  
# 回到上一个commit的版本,hard参数表示同时重置工做区的修改
git reset --hard HEAD^

# 撤销0ffaacc此次提交
git revert 0ffaacc     
# 撤销最近一次提交
git revert HEAD       
# 撤销最近2次提交,注意:数字从0开始
git revert HEAD~1      

# 回退后要执行强制推送远程分支
git push -f 
复制代码

git reset和git revert的区别

  • reset是根据来移动HEAD指针,在该次提交点后面的提交记录会丢失。

hlh0kowt3hov1xhcku38.gif

  • revert会产生新的提交,来抵消选中的该次提交的修改内容,能够理解为“反作”,不会丢失中间的提交记录。

3kkd2ahn41zixs12xgpf.gif

  • 使用建议
    • 公共分支回退使用git revert,避免丢掉其余同事的提交。
    • 本身分支回退可以使用git reset,也可使用git revert,按需使用。

挑拣代码

git cherry-pick

  • “挑拣”提交,单独抽取某个分支的一个提交点,将这个提交点的全部修改内容,搬运到你的当前分支。
  • 若是咱们只想将其余分支的某个提交点合并进来,不想用git merge将全部提交点合并进来,就须要使用这个git cherry-pick
git cherry-pick <commit-id>
复制代码

2dkjx4yeaal10xyvj29v.gif

暂存代码

git stash

  • 当咱们想要切换去其余分支修复bug,此时当前的功能代码还没修改完整,不想commit,就须要暂存当前修改的文件,而后切换到hotfix分支修复bug,修复完成再切换回来,将暂存的修改提取出来,继续功能开发。
  • 还有另外一种场景就是,同事在远程分支上推送了代码,此时拉下来有冲突,能够将咱们本身的修改stash暂存起来,而后先拉最新的提交代码,再pop出来,这样能够避免一个冲突的提交点。
# 将本地改动的暂存起来
git stash 
# 将未跟踪的文件暂存(另外一种方式是先将新增的文件添加到暂存区,使其被git跟踪,就能够直接git stash)
git stash -u 
# 添加本次暂存的备注,方便查找。
git stash save "message" 
# 应用暂存的更改
git stash apply 
# 删除暂存
git stash drop 
# 应用暂存的更改,而后删除该暂存,等价于git stash apply + git stash drop 
git stash pop
# 删除全部缓存
git stash clear
# 查看缓存列表
git stash list
复制代码

打印日志

  1. git log

能够显示全部提交过的版本信息,若是感受太繁琐,能够加上参数  --pretty=oneline,只会显示版本号和提交时的备注信息。

  1. git reflog

git reflog 能够查看全部分支的全部操做记录(包括已经被删除的 commit 记录和 reset 的操做),例如执行 git reset --hard HEAD~1,退回到上一个版本,用git log是看不出来被删除的,用git reflog则能够看到被删除的,咱们就能够买后悔药,恢复到被删除的那个版本。

Git的下载、配置、工具推荐

  • Git下载地址
  • 两种拉取代码的方式
    • https:每次都要手动输入用户名和密码
    • ssh :自动使用本地私钥+远程的公钥验证是否为一对秘钥
  • 配置ssh
    • ssh-keygen -t rsa -C "邮箱地址"
    • cd ~/.ssh切换到home下面的ssh目录、cat id_rsa.pub命令查看公钥的内容,而后复制
    • github的settings -> SSH and GPG keys-> 复制刚才的内容贴入 -> Add SSH key
    • 全局配置一下Git用户名和邮箱
      • git config --global user.name "xxx"
      • git config --global user.email "xxx@xx.com"
      • image.png
  • Git 相关工具推荐
    • 图形化工具 SourceTree :可视化执行git命令,解放双手
    • VSCode插件 GitLens:能够在每行代码查看对应git的提交信息,并且提供每一个提交点的差别对比

结尾

阅读到这里,是否是感受对Git相关概念更加清晰了呢,那么恭喜你,不再怕由于误操做,丢失同事辛辛苦苦写的代码了,并且将在平常工做的协同中游刃有余。

  • 💖建议收藏文章,工做中有须要的时候翻出来看一看~
  • 📃创做不易,若是个人文章对你有帮助,辛苦大佬们点个赞👍🏻,支持我一下~
  • 📌若是有错漏,欢迎大佬们指正~
  • 👏欢迎转载分享,请注明出处,谢谢~

参考

相关文章
相关标签/搜索