本文将从 Git 入门到进阶、由浅入深,从常用命令、分支管理、提交规范、vim 基本操作、进阶命令、冲突预防、冲突处理等多方面展开,足以轻松应对工作中遇到的各种疑难杂症,如果觉得有所帮助,还望看官高抬贵手给个赞呗,感谢!

虽说现在工作中使用 Git 都会用一些图形化管理工具来提高开发效率。可事实上使用图形管理化工具的前提,也是基于对命令都基本了解。还有比如我平时用的工具 Github Desktop 因为不带第三方合并工具,只能手动解决冲突,而且有的功能没有,只能配合自己手动敲命令。

即使是工具也没有那么完美的工具,掌握命令才是,工具只是。其他的 Git 可视化管理工具比如:小乌龟、SourceTree、还有我们开发用的 IDE 集成的,本篇不过多介绍。

基本概念

Git 是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。

Git 的作用与好处是:

可以帮我们保存文件的所有修改记录,并且使用版本号进行区分,让我们随时可以浏览历史版本、对比不同版本的差异、还原到指定版本,起到恢复和保护作用的同时,还能和其他人同时修改,然后通过 Git 来合并修改的部分文件,超级方便。主要有以下特点:

  • 分支更快、更容易。
  • 支持离线工作;本地提交可以稍后提交到服务器上。
  • Git 提交都是原子的,且是整个项目范围的,而不像 CVS 中一样是对每个文件的。
  • Git 中的每个工作树都包含一个具有完整项目历史的仓库。
  • 没有哪一个 Git 仓库会天生比其他仓库更重要。

不熟的同学别和 Github 搞混了,Git 是工具,Github 是平台,没有什么必然的联系,就像 Java 和 JavaScript 也没有什么必然联系一样

Github 是一个主流的代码托管平台。可以理解为存放和管理代码的网盘,可以把自己的代码传上去进行共享和维护。

安装配置

安装地址:Git - Downloads (git-scm.com)

安装好后,命令行窗口是使用 Git BashCMDPowershell终端、或者编译器内置的都行,这个就看个人喜好。

接着可以再配置下默认用户名和邮箱,比如配置全局的就用如下两条命令,替换成自己的用户名和邮箱,以后所有的项目都会默认这里配置的用户信息

git config --global user.name 'xxxx'
git config --global user.email 'xxxx@xx.com'

如果只需要在某个特定的项目中用其他的名字和邮箱,不用全局的,就把上面命令中的 --global 去掉在项目下执行即可,或者不执行命令,直接在项目下的 .git/config 文件里添加如下,也可以

# xxx 指的是填你自己的用户名和邮箱,不是真的写 xxxx 上去
[user]
name = xxxx
email = xxxx@xx.com

基本操作

先了解一下几个基本概念:

  • 工作区:开发的地方,开发过程就是对工作区的操作
  • 暂存区:执行 git add xxx 命令后,会把当前修改过的文件添加到暂存区
  • 本地仓库:执行 git commit 命令完成后,会把当前暂存区的文件放入本地仓库
  • 远程仓库:就是用来托管代码的服务器(如:Github、Gitee、GitLab、工蜂、Bitbucket..),执行 git push 命令后,会把本地仓库的文件提交到远程仓库

常见选项

再认识一下几个后面会用到多次的命令。

命令 缩写 意思
--all -a 全部
--force -f 强制
--delete -d 删除
--delete --force -D 强制删除
--move -m 移动或重命名
--move --force -M 强制移动或重命名
-u 设置默认远程分支

基本用法

上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。

  • git add *files* 把当前文件放入暂存区域。
  • git commit 给暂存区域生成快照并提交。
  • git reset -- *files* 用来撤销最后一次git add *files*,你也可以用git reset 撤销所有暂存区域文件。
  • git checkout -- *files* 把文件从暂存区域复制到工作目录,用来丢弃本地修改。

你可以用 git reset -p, git checkout -p, or git add -p进入交互模式。

也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。

  • git commit -a 相当于运行 git add 把所有当前目录下的文件加入暂存区域再运行。git commit.
  • git commit files 进行一次包含最后一次提交加上工作目录中文件快照的提交。并且文件被添加到暂存区域。
  • git checkout HEAD -- files 回滚到复制最后一次提交。

拉取远程项目

拉取远程项目到本地,先复制远程项目链接,再在本地执行如下命令

# 拉项目
git clone https://xxxx
# 拉项目的同时自动初始化并更新项目中的每一个子模块
git clone --recursive https://xxxx

上传本地项目

本地新建的项目,还没有提交到远程仓库,就需要先关联远程仓库。先在远程创建一个空项目,并复制该项目的链接,然后在本地项目根目录依次执行下面命令即可

git init                             // 初始化本地 Git 仓库,会生成一个 .git 隐藏文件夹
git remote add origin https://xxxx // 将本地项目关联远程仓库,后面的 https://xxxx 就是复制的远程仓库的链接
git pull --rebase origin master // 上传之前更新一下,确保没有冲突,master 为分支名称,--rebase 后面有介绍
git add . // 添加目录下所有发生改变的文件
git commit -m 'xxx' // 添加注释信息
git push -u origin master // 提交到 master 分支

其中 git remote add origin https://xxxx,就是往 .git/config 文件里添加下面这一段,手动添加也可以,意思就是与远程仓库建立关联。其他的几条命令后面有介绍,我们先认识下 origin 为后面做铺垫;

[remote "origin"]
url = https://github.com/rdif/xxxx.git
fetch = +refs/heads/*:refs/remotes/origin/*

命令里的 origin 类似变量命名,这是默认的而已,没什么特别的意思,可以随便写,假如改成 abc,后面的 git push origin xxx 改成 git push abc xxx 即可,方便区分远程仓库的

由此可得出一个结论,就是一个项目可以关联多个远程仓库,命不同的名就行了

没错

git remote -v 可以快速查看当前已经关联的远程仓库列表

关联多个远程仓库

可以使用 git remote add xxx 添加多个,或者直接动在 .git/config 文件里添加。

比如一个项目同时关联一个 Github 仓库和一个 Gitee 仓库,添加一个 remote 就是了,比如如下:

[remote "github"]
url = https://github.com/rdif/xxxx.git
fetch = +refs/heads/*:refs/remotes/github/*
[remote "gitee"]
url = https://gitee.com/xxxx/xxxx.git
fetch = +refs/heads/*:refs/remotes/gitee/*
[remote "all"]
url = https://github.com/rdif/xxxx.git
url = https://gitee.com/xxxx/xxxx.git
fetch = +refs/heads/*:refs/remotes/all/*

这样当我们提交代码的时候,想提交到 Github 就用 git push github master,想同时提交到 GithubGitee 的仓库,只需要 git push all master 即可

以命令的方法在某个 remote 下添加 url 如下,比如在上面 remote github 下再添加一个 url

git remote set-url --add github https:/xxxx.git

常用命令 add/commit/fetch/merge/pull/push

git add

# 添加一个文件 test.js 到暂存区,多个文件以空格隔开
git add test.js
# 添加全部文件到暂存区
git add .

git commit

# 会打开 vim 编辑器,vim 编辑器操作在下面展开说明
git commit
# 提交暂存区的文件到本地仓库,并备注当前 commit 记录
git commit -m '备注信息'
# 相当于 git add . 加上 git commit -m 'xxxx'
git commit -am 'xxxx'
# 用本地提交替换上次提交,比如不想保留上一次提交或者上一次提交描述信息写错了之类的
git commit --amend

git fetch

# 获取 remote origin 对应远程仓库指定 master 分支的变更,但是不和本地的合并
git fetch origin master
# 意思一个样,拉默认的分支而已
git fetch origin
# 也是,等效于 git fetch origin master:master,就是分支配置的默认值
git fetch
# 获取默认远程仓库所有分支的变更
git fetch -a

git merge

# 把本地的 test 分支分并到我当前分支
git merge test
# 合并 remote origin 对应远程仓库的 master 分支到当前分支
git merge origin/master
# --on-ff 是 no-fast-forward简写,合并并且会在分支上重新生成一个新的 commit 节点
git merge --on-ff origin/master
# 加入 --squash 表示合并,但是不生成 commit 记录,通常用于把本地分支合入远程分支
git merge test --squash
# 取消合并
git merge --abort

git pull

pullfetch 都是下载远程分支,区别是 pull 会和当前分支合并,fetch 不会

# 拉取 remote origin 对应的远程仓库的 master 分支合并到本地的 test 分支
git pull origin master:test
# 这种同理就不解释了
git pull origin
# git pull --merge 的简写,默认是 --merge 模式
# 等于 git fetch 加上 git merge,拉远程默认分支到当前分支
git pull
# 把合并模式切换成 rebase,等于 git fetch 加上 git rebase,rebase 后面进阶有介绍
git pull --rebase origin master

git push

# 推送本地 test 分支到 remote origin 对应的远程仓库的 master 分支
git push origin test:master
# 上面同理,推送到远程默认分支
git push origin test
# 缩写,同理,用默认分支
git push origin
git push # 相当于 git push origin master 加上 git branch --set-upstream master origin/master
# 推送并设置默认远程分支
git push -u origin master
# 强制推送,就算本地和远程有差异也推上去
git push -f origin master
# 删除远程主机的 master 分支
git push origin -d master

vim 基本操作

一点点小插曲

比如 git commit 就会打开一个 vim 的终端编辑器,让我们写提交说明,新手很容易在这个编辑器上面踩坑,不知道怎么输入,不知道怎么退出,最后只能关闭终端窗口,这也没办法,vim 的操作确实有些反人类。

vim 打开默认是不能输入的,要按 a 或者 i 进入编辑模式,输入完成后,再按 Esc 退出编辑模式,这时左下角会有输入框,输入如下英文字符,注意冒号别打成中文字符,回车即可退出 vim 回到终端:

  • :w:保存
  • :q:退出
  • :wq:保存并退出
  • !:强制的意思,不能保存时 :w! 强制保存,不能退出时 :q!:wq! 强制退出

我们继续 git

分支管理 branch/switch/checkout

一个人玩,可能分支的作用没那么大,但是团队协作,离不开分支管理。

比如本文开头图片那样一个版本一个分支多方便,是吧

或者现有一个新需求一个页面分为多个模块,分配给多个人负责,每人做一个模块,最后合并成一个完整的页面,如果都在同一个分支上开发,各种逻辑相互穿插,那冲突真的是人都要搞麻了,如果每个人都新建一个分支,开发自己负责的那个功能,最后再合并到同一个分支上去就非常方便了

然后因为多人协作肯定不是在一台电脑上,所以就需要一个服务器,来搭建一个 Git 仓库服务,或者用公共的云服务器仓库存储,常见的代码托管平台有比如:Github码云(Gitee)腾讯工蜂GitLabBitbucket...,关于这个本篇文章不过多展开。

创建分支

# 创建本地分支 test,但不切换
git branch test
# 创建 test 分支,并切换到 test 分支
git branch -M test
# 创建 test 分支,并切换到 test 分支
git checkout -b test
# 创建 test 分支,并切换到 test 分支
git switch -c test
# 创建本地与远程对应的 test 分支,并切换到 test 分支,全称最好一致
git checkout -b test origin/test

查看分支

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

切换分支

checkoutswitch 的共同点是都能切换分支,不同点是:

  • switch 语义上好点
  • switch 仅仅用于切换和创建并切换,checkout 还能用来还原工作区,后面进阶那有介绍
# 切换到 test 分支
git checkout test
# 新建 test 分支,并切换到 test 分支
git checkout -b test # 切换到 test 分支
git switch test
# 新建 test 分支,并切换到 test 分支
git switch -c test

删除分支

# 删除本地 test 分支
git branch -d test
# 删除远程主机的 master 分支
git push origin -d master

删除分支后恢复

# 查看记录,找到对应的 hash
git reflog
# 创建test分支,并取对应hash分支所有内容,相当于恢复了被删除的分支
git checkout -b test hash

重命名分支

# 把本地的 master 分支重命名为 test
git branch -m master test
# 远程分支没法直接重命名,只能删了重建,主要分几步
# 1. git push origin --delete test 删除远程分支
# 2. git push origin newtest 上传新的远程分支
# 3. 把修改后的本地分支关联远程分支
git branch --set-upstream-to origin/newtest

合并分支

其实就是上面的 git merge。比如要把 test 分支合并到 master 分支,就:

# 先切换到 master 分支
git checkout master
# 拉一下,看有没有更新
git pull
# 把 test 分支合进来
git merge test
# 查看状态,看有没有冲突的,有就打开 IDE 解决一下
git status
# 然后 add、commit、push 几个命令来一轮就 ok 了

git commit 提交规范

git commit 提交规范指的就是 git commit -am 'xxxx' 里的 xxxx 的书写规范,比如我在工作中开发了一个新功能提交的时候一般这么写:

  • git commit -am 'feat: 添加扫码登录
  • git commit -am 'feat(mobile):添加扫码登录,或者加个范围说明是添加哪方面的功能

feat 就是添加新功能的时候用,更多说明如下:

  • feat:添加新功能
  • fix:修复问题/BUG
  • style:注意不是指CSS,而是修改了如空格、缩进、逗号等代码风格相关,且不影响运行结果的
  • perf:优化相关的,比如功能优化、性能提升、提升体验等
  • refactor:代码重构,没有加新功能或者修复 bug
  • revert:撤消编辑,回滚到上一个版本、撤销上一次的 commit 之类的
  • test:测试相关,比如单元测试、集成测试等
  • docs:修改文档/注释,比如 README、CHANGELOG、CONTRIBUTE 等
  • chore:依赖更新/脚手架配置修改等,比如有改变构建流程、或者增加依赖库、工具之类的
  • workflow:工作流程改进
  • ci:持续集成
  • types:类型定义文件更改

到这里,基础部分内容就结束了

问个问题:git branch -M ac 是啥意思?不许翻上面

进阶操作

常用命令

Git 别名(alias)

命令难记?没有关系

Git 并不会在你输入部分命令时自动推断出你想要的命令。 如果不想每次都输入完整的 Git 命令,可以通过 git config 文件来轻松地为每一个命令设置一个别名。

// 配置全局 branch 命令别名为 b
git config --global alias.b branch

然后比如想创建一个名为 test 的本地分支,如下即可

git b test

在创建你认为应该存在的命令时这个技术会很有用。

检出 git checkout/git restore

checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。

restore指令使得在工作空间但是不在暂存区的文件撤销更改(内容恢复到没修改之前的状态)

# 四个都是:撤销 test.js 从上次提交之后的所有修改
git checkout -- test.js
git checkout - test.js
git checkout test.js
git restore test.js # 只把 test.js 还原成上一个版本的,HEAD^表示上一个版本,HEAD^^上上一个版本
git checkout HEAD^ - test.js
# 只把 test.js 重置到某个指定版本
git checkout commitID test.js
# 把 master 分支的 test.js 拿过来替换当前分支的 test.js
git checkout master - test.js # 都是撤销上一次 commit 之后的所有文件的所有修改
git checkout -- *
git checkout -- .
git checkout .
git restore . # 把暂存区的 test.js 重新放回工作区,和下面的 git reset HEAD test.js 作用一样
git restore --staged test.js

重置 git reset

git reset 通常用来把代码重置到过去的某个版本,有五种模式(--mixed--soft--hard--merge),注意看注释有说明区别。

另外 git reset 比较暴力,要慎用,比如现在提交五次了,然后使用这个命令重置到第一次,那么第二三四五次提交记录会全部没了的,找不回来的,这种情况记得新建个分支来执行这种操作就没事了,或者使用 git revert

# 后面一长串就是我复制的 commitID 或者说是 hash,长得就是这样子的
# 等同于 git reset commitID,因为 --mixed 是默认模式,所以可以不写
# 重置并撤销 git commit 以及 git add,保留编辑器中所有修改
git reset --mixed afcfbcb940164de24cc4f8c866e1da3a18382e10 # 重置并撤销 git commit,但不撤销 git add,保留编辑器中所有修改
git reset --soft commitID # 重置并撤销 git commit 以及 git add,并且删除编辑器中所有修改
git reset --hard commitID # 取消某次合并
git reset --merge commitID git reset --keep commitID # 把暂存区所有文件退回到工作区,相当于撤销 git add .
git reset HEAD
# 把暂存区的 test.js 重新放回工作区,和 git restore --staged test.js 作用一样
git reset HEAD test.js
# 重置到上一个版本
git reset --hard HEAD^
# 重置到上上一个版本,以此类推
git reset --hard HEAD^^
# 重置到指定版本
git reset --hard commitID

commitID 可以通过三种方法查看

  1. 执行 git log 命令能看到当前分支本地所有提交记录,上面每一条记录都有对应一个 commitID
  2. 去远程代码仓库查看历史提交记录,那里每一条提交记录都有一个对应的 commitID
  3. git tag 查看标签列表,如果有的话,再 git show 标签名 查看标签详情,里面也会有 commitID
# 查看当前分支所有提交记录,详细列表,一条记录有几行信息
git log
# 查看当前分支所有提交记录,简要列表,一条记录一行
git log --pretty=oneline
#
git log --oneline -n5

另外关于叫法本地仓库一般说重置、还原、撤销都行,远程仓库一般叫回滚

还原 git revert

git revertgit reset 有点类似,只是比 reset 稍微温柔一点,没那么暴力。git revert是用于“反做”某一个版本,以达到撤销该版本的修改的目的。

上面介绍了假如现在是第五版,用 reset 在重置回第一版本的时候,二三四五版全都会没了,而 revert 重置回第一版的时候,只是新增一条提交记录“第六版”,代码变成第一版的代码,原本的一二三四五版记录都会有

另外 revert 还要分两种情况,一种是还原正常的 commit,也就是 git commit 提交的 commit,另一种是用 merge 合并的 commit,如下

# 第一种查看正常提交的 commit,如下
git show 68be9e548
commit 68be9e548dadbe7b9677874b705662a8f95efd21 # 第二种查看 merge 合并的 commit 如下,多了一行 Merge,后面指的是从哪两个 commit 合并过来的
git show 9c810c1db
commit 9c810c1dbf72627dbff10d621c2974b32ed6d929
Merge: 3f6acb587 68be9e548
# 撤销正常提交的 commit
git revert commitID # 撤销 merge 的 commit 提交需要加参数来区分撤销哪一个分支上的内容
# 也就是指定上面 Merge: 3f6acb587 68be9e548,这两个 id 中的哪一个
# -m 接收一个参数是数字,取值 1 或 2,表示 Merge 的第一个还是第二个 id
git revert -m 1 9c810c1db
# 删除最后一次远程提交
git revert HEAD
git push origin master git reset --hard HEAD^
git push origin master -f # 还原某次提交
git revert commitID

挑拣 git cherry-pick

比如有两个分支 master 和 test,在 test 上修改了,并且提交了 commit 之后,这时候想把这次的提交也给弄到 master 上,就可以复制 test 的 commitID,再换到 master 分支后执行 git cherry-pick commitID 就可以了

what?这不就是 merge?

和 merge 不同的是:cherry-pick 合并的是某一次 commit 提交的文件,merge 合并的是整个分支。且 merge 会额外多一条 merge commit 的记录,而 cherry-pick 不会。

而且 cherry-pick 更加灵活,在需要把某个/或多个分支中的 commit,合入其他分支的时候都可以用,示例如下

# 这样就把其他分支的一个 commit 合入当前分支了
git cherry-pick commitID # 如果需要把多个 commit 合过来如下,这多个 commitID 可以是来自不同分支的
git cherry-pick commitID1 commitID2 commitID3

变基 git rebase

git rebasegit merge 的区别

git merge 和 git rebase 都是可以合并分支,合并用法也是一样,不同的一个是在 commit 记录的处理上:

  • git merge 会新建一条新的 commit,然后两个分支以前的 commit 记录都指向这个新 commit 记录。这种方法会保留之前每个分支的 commit 历史。
  • git rebase会先找到两个分支的第一个共同的 commit 祖先记录,然后将提取当前分支这之后的所有 commit 记录,放到目标分的最新提交后面。经过这个合并后,两个分支合并后的 commit 记录就变为了线性的记录了。

这么说可能不太好理解,看如下示例:

# 如下,需要把本地 test 分支合入 dev
# 为方便理解,字母表示commit记录,数字表示提交时间顺序,可以理解为1就是1点提交的
dev -> A1 -> B3 -> 这一行是远程 dev 分支的commit记录,A1/B3是你同事提交的
X2 -> Y4 这一行是拉取了 dev 分支后在本地的 test 分支 commit 记录 # 现在需要把你本地的分支合并到远程的分支去
# 用merge合并后,dev 分支看到的记录是这样的,M为merge记录的commit
dev -> A1 -> X2 -> B3 -> Y4 -> M # 用rebase合并后,dev 分支看到的记录是这样的,注意顺序,且没有合并记录的commit
# 简单说就是直接把 test 分支的所有新的 commit 拿出来直接拼到 dev 分支末尾,不管提交时间先后
dev -> A1 -> B3 -> X2 -> Y4
  • 然后是解决冲突的问题上,merge 是解决一次冲突就行了,rebase 需要一次一次地解决,如上示例的记录顺序也能看出来
  • 再就是 rebase 可以合并多次 commit。比如本地分支提交了三个 commit,但没有 push 到远程,最后想提交到远程的时候,为了简洁,我们希望把本地的三个 commit 合并成一个 commit 再提交到远程,远程只产生一条 commit 记录,就可以用 git rebase -i 处理下先,这命令可以删除指定记录,或者合并多个 commit,对 commit 消息编辑等
# 删除某次提交,^表示 commitID 的前一次提交
git rebase -i 'commitID'^
# 修改多个提交信息
git rebase -i HEAD~3

贮藏 git stash

git stash 常用于把修改储存起来,需要的时候再取出来。常用于:

  • 切换分支并且需要保留修改的时候
  • 切换分支并且需要把修改带到新的分支的时候
# 把当前分支的修改储存起来,两个一样的
git stash
git stash save
# 存储并添加备注,方便查找
git stash save '备注信息'
# 查看储存列表
git stash list
# 取出储存中最近一次的修改并删除储存记录
git stash pop
# 取出储存中的指定部分修改,stash@{0} 0是默认的不写也行,是啥只要查看储存列表你就知道了
git stash apply stash@{0}
# 删除指定储存
git stash drop stash@{1}
# 删除所有的储存
git stash clear
# 创建一个新分支 test,并恢复储存工作时所在的提交到该分支上,并扔掉储藏
git stash branch test stash@{1}
# 不储存暂存区的,也就是 git add 了的
git stash --keep-index

清理 git clean

git reset 的区别是:reset 删除的是己跟踪的文件,并且将已 commit 的回退。clean 删除的是未跟踪的文件/目录

# 显示如果执行后面删除的命令将会删除的文件和目录,相当于给提前给我们确认下
git clean -n
# 删除工作目录中所有没被追踪的文件(-f)以及空的子目录(-d),一起就是 -df
git clean -df

差异 git diff

用来找出仓库或者文件之间的差异,可以用来预测或者阻止可能产生冲突的合并

# 工作区 vs 暂存区
git diff
# 工作区 vs 版本库
git diff head
# 暂存区 vs 版本库
git diff –cached

有多种方法查看两次提交之间的变动,如下面是一些示例。

问题预防

  • 不要对已经提交到远程仓库的 commit 进行 rebase 变基操作,除非是你一个人玩的分支
  • 在切换分支,或者合并分支,或者重置/回滚之前,最好不要有未 commit 的文件,如果有并且不想提交就用 git stash 先存起来,再执行操作,如果用命令操作的话,取出之后记得清理
  • 远程仓库回滚前记得做好备份,比如拉一个分支在本地。并且需要通知团队其他成员,不要悄摸摸地就搞了

解决问题

切换分支保留修改

有时候比如我们在 test 分支上开发了一半,由于某些原因需要切换到 master 分支,但现在又不想提交,又想保留修改并且不带到 master 分支上去,就可以这样:

# 把当前分支的修改储存起来
git stash
# 切换到其他分支干你的事
git checkout master
# 干完了
# 切换回 test 分支
git checkout test
# 取出储存中所有的修改
git stash pop
# 删除所有的储存
git stash clear

切换分支转移修改

有的时候我们需要在 test 分支上开发,但是忘记了,活快干完了才发现当前原来是 master 分支,可是已经开发了,这时候就需要切换分支到 test,并且把已经开发的部分内容也从 master 分支带到 test 分支来,就可以这样:

# 储存修改
git stash
# 切换到 test 分支
git checkout test
# 取出储存中的全部修改
git stash pop
# 或者
# 查看储存列表
git stash list
# 取出储存中的指定部分修改,stash@{0} 是啥只要查看储存列表你就知道了
git stash apply stash@{0}
# 再清掉储存
git stash clear

合并时发生冲突用 git merge abortgit reset --merge 都可以取消合并

比如把不想要的代码 commit 了,但是没有 push 比如刚更新的代码出问题了,需要还原这次提交的代码 比如某次提交了不想提交的东西,需要清除掉它

revert 之后重新上线 diff 丢失

  • 比如在 dev 分到开发了个功能,提交后会产生一条 commit 记录,为了方便理解,我们先把这次提交标记为 a
  • 然后合并到 master 后,我们把这次合并记录标记为 b
  • 结果出现了 bug 需要撤销合并,使用 revert b 撤销了,这会产生了一条新的记录 我们标记为 c
  • 然后继续在 dev 分支开发完成提交,提交记录标记为 d
  • 这时候再合并到 master 上去,此时合并后的内容不会包含 a 的提交,因为 a 被 revert 丢弃过,不会参与 diff,如果需要包含 a,需要先 revert c 意思是撤销某一次的撤销,再来合并,就 ok 了

合并冲突不想合并了

合并时、或者拉取时等,发现有冲突,可能是其他同事提交的,自己不知道怎么冲突怎么选择,或者其他原因,总之不想合并了,都可以用 --abort 取消,比如合并的时候发现有冲突不想合并了

git merge --abort 取消合并即可

解决冲突

有的时候合并分支冲突是由于本地主分支没有更新导致,或者有时 git pull 的时候冲突,只需要掉本地主分支,再重新拉一下远程分支就好了。

有的时候冲突就只能解决冲突,使用 git status 看由于冲突导致没有合并成功的文件是哪些,然后去编辑器打开冲突的文件即可,也可用 cat <文件路径> 查看指定文件里冲突的部分,直接去编辑器改

或者就是用命令,比如把 test 分支,合入 master 分支时产生冲突。

# 只保留 test 的修改
git checkout --theirs test.js
# 只保留 master 的修改
git checkout --ours test.js
# 都保留
git checkout --ours/theirs test.js
# 查看冲突,都行
git diff --theirs
git diff --ours # 这个 --theirs 和 --ours 是啥?比如冲突的时候是这样的
# <<<<<<<<< HEAD
# console.log('master') // 这个就是 --ours
# =========
# console.log('test') // 这个就是 --theirs
# >>>>>>>>> test

Git与SVN的最主要的区别?

Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑 上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各 自的修改推送给对方,就可以互相看到对方的修改了。

SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活, 干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网 速慢的话,就纳闷了。

参考资料:

图解GIT: http://marklodato.github.io/visual-git-guide/index-zh-cn.html

Git官方:https://git-scm.com/

Git参考手册:https://git-scm.com/docs

结语

如果本文对你有一点点帮助,点个赞支持一下吧,你的每一个【赞】都是我创作的最大动力 _

更多干货技术文章可前往:http://www.guosisoft.com/article,大家一起共同交流和进步呀!

干货|工作中要使用Git,看这篇文章就够了的更多相关文章

  1. Vue开发入门看这篇文章就够了

    摘要: 很多值得了解的细节. 原文:Vue开发看这篇文章就够了 作者:Random Fundebug经授权转载,版权归原作者所有. 介绍 Vue 中文网 Vue github Vue.js 是一套构建 ...

  2. 想让安卓app不再卡顿?看这篇文章就够了

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由likunhuang发表于云+社区专栏 实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一.Android 由于机型配置和系统的 ...

  3. 数据可视化之PowerQuery篇(四)二维表转一维表,看这篇文章就够了

    https://zhuanlan.zhihu.com/p/69187094 数据分析的源数据应该是规范的,而规范的其中一个标准就是数据源应该是一维表,它会让之后的数据分析工作变得简单高效. 在之前的文 ...

  4. 还不会Traefik?看这篇文章就够了!

    文章转载自:https://mp.weixin.qq.com/s/ImZG0XANFOYsk9InOjQPVA 提到Traefik,有些人可能并不熟悉,但是提到Nginx,应该都耳熟能详. 暂且我们把 ...

  5. 讲真,MySQL索引优化看这篇文章就够了

    本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引背后的数据结构三部分相关内容,下面一一展开. 一.MySQL——索引基础 首先,我们将从索引基础开始介绍一下什么 ...

  6. spring boot入门,看这篇文章就够了

    一.SpringBoot入门 1.基本介绍 简化Spring应用开发的一个框架.整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 优点: 快速创建独立运行的Spring项目以及与主 ...

  7. 想要彻底搞懂大厂是如何实现Redis高可用的?看这篇文章就够了!(1.2W字,建议收藏)

    高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间. 假设系统一直能够提供服务,我们说系统的可用性是100%.如果 ...

  8. MySQL索引优化看这篇文章就够了!

    阅读本文大概需要 5 分钟. 来源:cnblogs.com/songwenjie/p/9410009.html 本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引 ...

  9. Kafka面试,看这篇文章就够了

    原文链接:https://mp.weixin.qq.com/s/zxPz_aFEMrshApZQ727h4g** 引言 MQ(消息队列)是跨进程通信的方式之一,可理解为异步rpc,上游系统对调用结果的 ...

  10. 微信小程序获取手机号码看这篇文章就够了

    前言 微信小程序获取手机号码,从官方文档到其他博主的文档 零零散散的 (我就是这样看过来 没有一篇满意的 也许是我搜索姿势不对) 依旧是前人栽树 后人乘凉 系列.保证看完 就可以实现获取手机号码功能 ...

随机推荐

  1. 【javascript】关于 canvas.toDataURL()

    在工作中遇到了奇怪的问题,在此记录. 一.定义 canvas.toDataURL()方法是返回一个包含图片展示的 数据URL.可以使用 type 参数其类型,默认为 PNG格式,图片的分辨率为96dp ...

  2. Java基础学习——Arrays类

    1.数组复制 Arrays.copyOfRange(original, from, to) 此方法与System.arraycopy类似. 不同的是System.arraycopy需要提前声明目标数组 ...

  3. verilog 概念版

    一.MCU芯片的定义 MCU芯片是指微控制单元(MicrocontrollerUnit:MCU),又称单片微型计算机或者单片机,是把中央处理器的频率与规格做适当缩减,并将内存.计数器.USB.A/D转 ...

  4. UAC的详细讲解(转载)

    win32中也有对UAC的操作方法 网址:https://blog.csdn.net/zuishikonghuan/article/details/46965159?locationNum=7& ...

  5. jvm垃圾收集器汇总

    1.吞吐量和延时 吞吐量:吞吐量指的是cpu的利用时间,计算公式是 运行用户代码时间  / (用户代码时间 + 垃圾收集时间),吞吐量越大说明cpu的利用率越大. 延时:延时指的是停顿时间,用户代码不 ...

  6. sql 查询大数据 常用 50列优化

    大数据量的问题是很多面试笔试中经常出现的问题,比如baidu google 腾讯 这样的一些涉及到海量数据的公司经常会问到. 下面的方法是我对海量数据的处理方法进行了一个一般性的总结,当然这些方法可能 ...

  7. mysql 存储国过程实现竖表变横表(将行数据值变为字段)

    示例: 表结构如下: CREATE TABLE `pressure` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `presurena ...

  8. Neo4j学习(1)--安装

    1.访问官网,下载Community版本,注意在下载页面已经提示了登录时的默认用户名和密码neo4j/neo4j.我使用的版本为3.4.10,jdk要求为java8 2.安装Windows版本,最好参 ...

  9. 全网最详细中英文ChatGPT接口文档(一)开始使用ChatGPT——导言

    目录 Introduction 导言 Overview 概述 Key concepts 关键概念 Prompts and completions 提示和完成 Tokens 标记/符号 Models 模 ...

  10. 2019徐州网络赛 M Longest subsequence 序列自动机

    题目链接https://nanti.jisuanke.com/t/41395 题意:给两个字符串,s和t,在s中求字典序严格大于t的最长子序列. 思路:分类讨论即可.先建个s的序列自动机. 1 如果有 ...