文章已同步至掘金:https://juejin.cn/post/6844904015654813710
欢迎访问😃,有任何问题都可留言评论哦~
Git 常用命令
初始化一个Git(本地)仓库 (只需初始一次)
git init
设置用户名和邮箱 (只需设置一次)
用户名:git config --global user.name 你的用户名
邮箱:git config --global user.email 你的邮箱
把工作区的文件添加到暂存区 (需按自己的需求添加N次)
git add 文件名,文件名····
git add * (把当前工作区所有文件添加到暂存区)
git add ./ (把当前工作区所有文件添加到暂存区)
commit版本
提交commit
git commit -m "说明文字"
提交(commit)时不进行eslint校验(不建议使用)
git commit --no-verify -m "描述信息"
追加版本,不重新生成commit:
git commit —amend
如果本地commit没有推送到远程仓库,则可以直接使用git commit —amend
追加
由于之前已经将该commit推送到远程仓库,导致修改后推送失败。
原因:如果你的commit已经push到了远程仓库,那么使用--amend
修改commit后,git push
时定要使用 --force-with-lease
参数来强制推送,否则就会报错。
流程:
- 确认最近一次commit节点是你要修改的commit节点
- 修改代码
- 修改完毕后执行:
git commit --amend -m "新修改的提交信息"
-m加一下比较好,跟上一次提交的-m一样也行,不然会出现vim界面(也是让你写注释)所以没必要 git push --force-with-lease
查看相关信息
查看用户名或邮箱等一系列设置 (可自行修改,按Q键退出)
git config --list
查看文件版本
git log
(查看分支上都有哪些版本)
git log --oneline
(查看分支上的版本,相对简洁)
查看文件状态
git status
查看文件版本id
git reflog
以图文形式查看文件版本
gitk
查看具体提交文件版本的信息
git show commit_id
查看执行 git status 的结果的详细信息
git diff
- 尚未缓存的改动:
git diff
- 查看已缓存的改动:
git diff --cached
- 查看已缓存的与未缓存的所有改动:
git diff HEAD
- 显示摘要而非整个 diff:
git diff --stat
撤回暂存区文件
撤回在暂存区的文件
git reset HEAD --
(撤回所有)
git reset HEAD -- 文件名
(撤回指定文件)
git checkout . #本地所有修改的。没有的提交的,都返回到原来的状态
git stash #把所有没有提交的修改暂存到stash里面。可用git stash pop回复。
git reset --hard HASH #返回到某个节点,不保留修改,已有的改动会丢失。
git reset --soft HASH #返回到某个节点, 保留修改,已有的改动会保留,在未提交中,git status或git diff可看。
git clean -df #返回到某个节点,(未跟踪文件的删除)
git clean 参数
-n 不实际删除,只是进行演练,展示将要进行的操作,有哪些文件将要被删除。(可先使用该命令参数,然后再决定是否执行)
-f 删除文件
-i 显示将要删除的文件
-d 递归删除目录及文件(未跟踪的)
-q 仅显示错误,成功删除的文件不显示
注:
git reset 删除的是已跟踪的文件,将已commit的回退。
git clean 删除的是未跟踪的文件
克隆仓库代码
克隆远程仓库的代码到本地
git clone 远程仓库地址
注:一般第一次用 git clone 远程仓库地址
进行拷贝,以后都用 git pull
进行拉取
克隆远程仓库指定分支的代码到本地
git clone -b 分支名 远程仓库地址
从远程仓库拉取代码到本地(master为主分支)
git pull 远程仓库地址 master
推送代码
推送本地代码到远程仓库(第一次同步时需输入密码)
git push 远程仓库地址 master
一般使用git push
就ok了
简便方式(一般不用这个,不用看):
添加远程仓库:git remote add origin 远程仓库地址
查看远程仓库:git remote
如果显示 origin 则说明添加成功,以后再推送代码到远程仓库时,只需输入git push origin master
就可以推送代码。
当使用代码git push -u origin master
时,表示把origin设置为默认主机,则再次推送代码时可简写为git push
注:如果当前分支与多个主机存在追踪关系,则可以使用 -u 选项指定一个默认主机,这样后面就可以不加任何参数使用git push
- 删除设置的origin(origin名称需根据你本地查询出来的名字进行删除)
查询:git remote -v
删除:git remote rm origin
打标签
查看本地分支标签
git tag
或者
git tag -l
或者
git tag --list
查看远程所有标签
git ls-remote --tags
或者
git ls-remote --tag
给当前分支打标签
- 轻量标签在Git中,是不存储任何的信息,只是一个特定提交的引用。
- 附注标签存储在Git数据中,且附注标签中包含了打标签者的名称、电子邮件,日期等信息,一般情况我们都会使用附注标签。
创建轻量标签(git tag
+ 标签名称
)
git tag 《标签名》
例如
git tag v1.1.0
创建附注标签(需要在创建轻量标签的方式上,添加选项-a
)
git tag -a 《标签名》
例如
git tag -a v1.1.0
使用-m
选项来指定存储在标签中的信息,如果添加了-m
选项,那么Git会绕过配置的编辑器
git tag -a v1.0.0 -m "发布版本v1.0.0"
给特定的某个commit版本打标签,比如现在某次提交的id为 02f498d
git tag v1.0.0 02f498d
或者可以添加注释
git tag v1.0.0 -m "add tags information" 02f498d
或者
git tag v1.0.0 02f498d -m "add tags information"
删除本地某个标签
git tag --delete v1.0.0
或者
git tag -d v1.0.0
或者
git tag --d v1.0.0
删除远程的某个标签
git push -d origin v1.0.0
或者
git push --delete origin v1.0.0
或者
git push origin -d v1.0.0
或者
git push origin --delete v1.0.0
或者
git push origin :v1.0.0
将本地标签一次性推送到远程
git push origin --tags
或者
git push origin --tag
或者
git push --tags
或者
git push --tag
将本地某个特定标签推送到远程
git push origin v1.0.0
查看某一个标签的提交信息
git show v1.0.0
切换到标签
git checkout [tagname]
基于线上tag拉分支new_branch
git branch new_branch v1.2.0
Git 分支命令
注:origin是你的默认仓库地址,你也可以换成你的仓库地址链接(https://git…git)
查看分支
查看本地分支
git branch
查看远程分支
git branch -r
查看所有分支
git branch -a
创建分支
创建本地分支
git branch 分支名
创建远程分支
git push --set-upstream origin 分支名
根据某个commit创建本地分支
git checkout commit_id -b newBranch
切换分支
切换分支
git checkout 分支名
拉取远程分支并切换到该分支
git checkout -b 本地分支名 origin/远程分支名
或者 git checkout --track origin/远程分支名
或者 git checkout -t origin/远程分支名
或者 git fetch
(获取远程所有分支),假设有个分支叫origin/Test
,直接git checkout Test
即可,会在本地新建一个同名分支,并与远程分支关联
创建并切换分支
git checkout -b 分支名
合并分支
合并分支(合并分支之前需要切换到master分支上,合并完解决冲突需要push一下)
git merge 分支名
或者 git pull origin 分支名
但是我们平常不用这个指令来合并分支,我们通常使用
git merge --squash 分支名
。
–squash选项的含义是:本地文件内容与不使用该选项的合并结果相同,但是不提交、不移动HEAD,因此需要一条额外的commit命令。其效果相当于将分支上的多个commit合并成一个,放在当前分支上,原来的commit历史则没有拿过来。
判断是否使用–squash选项最根本的标准是,待合并分支上的历史是否有意义。如果没有意义,就可以直接使用带–squash这个指令。
使用这个命令之后,我们需要commit一次,在提交的我们最好加上标识,然后再进行push
如:git commit -m feat:"新功能"
- feat:新功能(feature)
- fix:修补bug
- docs:文档(documentation)
- style: 格式(不影响代码运行的变动)
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
删除分支
删除本地分支
git branch -d 分支名
删除远程仓库的分支
git push origin --delete 分支名
- 同步远程分支到本地
有很多在远程仓库已经删除的分支在本地依然可以看到
使用命令git remote show origin
,可以查看remote地址,远程分支,还有本地分支与之相对应关系等信息
使用git remote prune origin
命令,这样就删除了那些远程仓库不存在的分支
两个分支合并部分代码
master
主分支、develop
测试分支(包含全部代码)
现在只把develop
分支的部分代码合到master
上 (需保持两个仓库的代码为最新)
操作步骤:
- 基于
master
分支建立一个临时分支(feature)并切换到该分支上git checkout -b feature
- 用
develop
指定文件或文件夹替换feature
的相应文件git checkout develop <目标文件夹或目标文件名>
, 例如:此次开发只涉及 (src/pages/pools/) 文件夹下的文件,则执行:git checkout develop src/pages/pools/
,执行完此命令后,develop
分支的 (src/pages/pools/) 下的文件会替换feature
分支下相应的文件 - 将本次 checkout 内容提交到
feature
分支上git commit -m "描述信息"
,git push --set-upstream origin feature
- 切换至
master
分支并合并feature
分支代码到master
分支上git checkout master
,git merge feature
,git push
,或者使用操作面板合并 - 删掉临时分支
拉取指定分支的指定文件
git checkout 「branch」<file_name>
临时保存文件信息stash
用来临时地保存一些还没有提交的工作,以便在分支上不需要提交未完成工作就可以清理工作目录
git stash
添加备注,方便查找
git stash save "save message"
恢复未完成的工作状态
// 默认第一个
git stash pop
// 应用其他
git stash pop stash@{$num}
查看所有的stash
git stash list
查看stash具体内容
// 显示第一个储存
git stash show -p
// 查看其他存储
git stash show -p stash@{$num}
应用某个存储但不会把存储从存储列表中删除
// 默认第一个
git stash apply
// 其他
git stash apply stash@{$num}
丢弃某个stash
git stash drop stash@{$num}
删除所有缓存的stash
git stash clear
同一个项目,当你本地代码更改后,如果你的远程仓库的代码也更改了,这时候你要拉取远程仓库的代码,同时保证本地代码不被覆盖。
这时候就可以操作步骤:git stash
(保存当前的工作状态),git pull
(拉取远程仓库代码),git stash pop
(恢复之前的工作状态)
merge时忽略某个文件或文件夹
git 开启忽略文件配置
git config merge.ours.driver true //开启忽略文件配置
在项目根目录下新建文件.gitattributes,然后文件中写入需要忽略的文件名 + merge=ours, 一个文件占一行
readme.txt merge=ours
/public/scm/** merge=ours
git rebase使用
注意:
- 不要通过rebase对任何已经提交到公共仓库中的commit进行修改(你自己一个人玩的分支除外)
- 除非你可以肯定该分支只有你自己使用,否则请谨慎操作。
合并本地多次commit记录
本地开发的时候,在确认功能没问题之前,先不要推送到远程分支,除非测试需要,到时候可以往commit上面追加,尽量保证一个commit为一个功能等
命令:
git rebase -i [startpoint] [endpoint]
其中-i
的意思是--interactive
,即弹出交互式的界面让用户编辑完成合并操作,[startpoint]
[endpoint]
则指定了一个编辑区间,如果不指定[endpoint]
,则该区间的终点默认是当前分支
HEAD所指向的commit(注:该区间指定的是一个前开后闭的区间)
或者也可以使用:git rebase -i HEAD~3
来合并前三次提交
每一个commit id 前面的pick表示指令类型,git 为我们提供了以下几个命令:
- pick:保留该commit(缩写:p)
- reword:保留该commit,但我需要修改该commit的注释(缩写:r)
- edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
- squash:将该commit和前一个commit合并(缩写:s)
- fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
- exec:执行shell命令(缩写:x)
- drop:我要丢弃该commit(缩写:d)
例如:合并前三次提交,保留第一次提交可以使用:
p d2cf1f9 fix: 第一次提交
s 47971f6 fix: 第二次提交
s fb28c8d fix: 第三次提交
wq
保存退出
修改合并之后commit的描述信息,wq
保存退出即可
然后push推送到你的远程分支,如果出现推送失败,则可以使用--force-with-lease
强推,前提是这个分支只有你一个人在开发,否则可能会覆盖别人的代码
或者是用:
git merge --squash 分支名
git commit -m '修复了xxx'
git push
分支合并
rebase
做了什么操作呢?
首先,git会把本地分支里面的每个commit取消掉;
其次,把上面的操作临时保存成patch文件,存在.git/rebase目录下;
然后,把本地分支更新到最新的master分支
最后,把上面保存的patch文件应用到本地分支上
示例
- 远程主分支master
- 本地开发分支dev
当你在本地开发完成并且提交本地commit后(没有提交到远程仓库),这时候master分支有人已经把代码合上去了,所以现在master分支是领先于你的dev分支
这时候,使用rebase来操作一波,切到master分支,pull下代码,切到你的分支,执行git rebase master
,这时候看下log信息,你的commit是在master最新提交的commit之后的。
在 rebase
的过程中,也许会出现冲突 conflict
。在这种情况,git
会停止 rebase
并会让你去解决冲突。在解决完冲突后,用 git add
命令去更新这些内容。
注意:你无需执行 git-commit,只要执行 continue,git rebase --continue
,这样 git
会继续应用余下的 patch
补丁文件。
然后推送到远程,但是会报一个错,因为远程分支的commit跟你本地的commit是不一样的,如果这个分支只有你一个人在开发,那么强制推送即可,git push --force-with-lease
在任何时候,我们都可以用 --abort
参数来终止 rebase
的行动,并且分支会回到 rebase
开始前的状态。git rebase —abort
版本回退(分支亦可)
如果在开发中进行了错误提交,那么我们需要使用版本回退(回滚),使自己的工作树和远程仓库回到之前的版本。
对于版本回退,经常会用到两个命令:git reset
、git revert
具体有什么区别呢?
git reset
参数:
- 使用
soft
参数,恢复git commit
的操作 - 使用
hard
参数,恢复到最原始状态,本地代码也会更改 - 使用
mixed
参数,默认参数,恢复git add
的操作,包含恢复git commit
的操作 - 示例:使用
reset
参数,工作区的代码也会相应改变
git reset --hard HEAD^/commit_id
git reset --hard HEAD^ / HEAD~1
(表示回到上一个版本)
git reset --hard HEAD^^ / HEAD~2
(表示回到上上一个版本,依次类推)
git reset --hard 版本id
(回到指定的版本,一般用这个)
注:本地版本回退之后,远程仓库不回退(可push到远程仓库中,可能会报错,可以使用git push -f
强推上去,不推荐,建议看我下面版本回退方法)
- 回到未来版本(需通过git log查看版本id)
git reset --hard 版本id
git reset
假如我们的仓库有如下几个提交:
其中:A 和 B 是正常提交,而 C 和 D 是错误提交。现在,我们想把 C 和 D 回退掉。而此时,HEAD 指针指向 D 提交(5lk4er)。我们只需将 HEAD 指针移动到 B 提交(a0fvf8),就可以达到目的。
上面已经介绍过了,可以使用 git reset --hard a0fvf8
即可把HEAD指针移动B提交下,如图:
而这个时候,虽然本地仓库的HEAD指针变了,但是远程仓库的 HEAD 指针依然不变,仍在 D 提交上。所以,如果直接使用 git push
命令的话,将无法将更改推到远程仓库(报错)。此时,只能使用 -f 选项将提交强制推到远程仓库:git push -f
采用这种方式回退代码的弊端显而易见,那就是会使 HEAD 指针往回移动,从而会失去之后的提交信息。将来如果突然发现,C 和 D 是有用的代码,然而却已经无法复原了。但是我们可以使用 git revert
命令来解决这个问题。
git revert
使用git revert
会遇到两种情况,一种是回到提交(commit)之前,另一种是回到合并(merge)之前,两者使用方式不同。
回到提交(commit)之前
git revert
的作用是通过反做创建一个新的版本,这个版本的内容与我们要回退到的目标版本内容一样,但是HEAD指针是指向这个新生成的版本,而不是目标版本。
使用 git revert
命令来实现上述例子的话,我们可以这样做:先 revert D,再 revert C (有多个提交需要回退的话需要由新到旧进行 revert)
git revert 5lk4er
git revert 76sdeb
这里会生成两个新有提交:D’ 和 C’,如图:
这里只有两个提交需要 revert,我们可以一个个回退。但如果有几十个呢?一个个回退肯定效率太低而且容易出错。我们可以使用以下方法进行批量回退:git revert OLDER_COMMIT^..NEWER_COMMIT
,(例如:git revert 76sdeb^..5lk4er
)
这时,错误的提交 C 和 D 依然保留,将来进行甩锅的时候也有依可循。而且,这样操作的话 HEAD 指针是往后移动的,可以直接使用 git push
命令推送到远程仓库里。
回到合并(merge)之前
如果你进行了合并(merge)操作,那么使用上面的方式会报错error: commit commit_id is a merge but no -m option was given.
,原因是 :merge commit 和普通 commit 的不同之处在于 merge commit 包含两个 parent commit,代表该 merge commit 是从哪两个 commit 合并过来的。
可以使用git show merge_commit_id
来查看是从哪两个分支合并来的,例如(9834b9a是我合并后的commit_id):
-> git show 9834b9a
commit 9834b9abf40d4687ceed8616b86f906fbd249a74 (HEAD -> dev, origin/dev)
Merge: 1d3dc50 3b93623
Author: fanjunyang <996597002@qq.com>
Date: Sun Aug 30 13:18:38 2020 +0800
这代表该 merge commit 是从 1d3dc50 和 3b93623 两个 commit 合并过来的,而普通的 commit 则没有 Merge 这行。
这时候我们就需要添加-m
选项以代表这次 revert 的是一个 merge commit,这时需要指定一个 parent number 标识出"主线",主线的内容将会保留,而另一条分支的内容将被 revert。
从上面 git show 命令的例子中可以看到,merge commit 的 parent 分别为 1d3dc50 和 3b93623,其中 1d3dc50 代表 dev 分支(我的主分支,从图中可以看出),3b93623 代表 will-be-revert 分支(这里是dev1分支,我把dev1分支上的代码合到dev中了)。需要注意的是 -m
选项接收的参数是一个数字,数字取值为 1
和 2
,也就是 Merge 行里面列出来的第一个还是第二个。
我们要 revert will-be-revert 分支上的内容,即 保留主分支(dev),应该设置主分支为主线,操作:git revert -m 1 9834b9a
中间删除,两边保留
假如现在有三个提交,但很不巧的是,那个错误的提交刚好位于中间。如图:
这时,直接使用 git reset
命令将 HEAD 指针重置到 A 提交显然是不行的,因为 C 提交是正确的,需要保留的。这时候我们要先把 C 提交 及 B 批次全部回退,再使用 cherry-pick
命令(挑拣的意思)将 C 提交重新再生成一个新的提交 C’',这样就实现了将 B提交回退的需求。完整的过程如图所示:
合并某个分支上单个commit
使用git log或查git log --graph --pretty=oneline --abbrev-commit 查看提交的信息,记住commit id.
git checkout [branch-name] 切换到合并的分支
git cherry-pick <commit-id> 把某个commit id提交合并到当前分支
如:
dd2e86 - 946992 -9143a9 - a6fd86 - 5a6057 [master]
\
76cada - 62ecb3 - b886a0 [feature]
比如,feature 分支上的commit 62ecb3 非常重要,它含有一个bug的修改,或其他人想访问的内容。无论什么原因,你现在只需要将62ecb3 合并到master,而不合并feature上的其他commits,所以我们用git cherry-pick
命令来做:
git checkout master 先切换到master分支
git cherry-pick 62ecb3 再使用cherry-pick命令
现在62ecb3 就被合并到master分支,并在master中添加了commit(作为一个新的commit)。cherry-pick 和merge比较类似,如果git不能合并代码改动(比如遇到合并冲突),git需要你自己来解决冲突并手动添加commit。
合并某个分支上的一系列commits
在一些特性情况下,合并单个commit并不够,你需要合并一系列相连的commits。这种情况下就不要选择cherry-pick了,rebase 更适合。
git checkout -b <newBranchName> <to-commit-id>
创建一个新的分支,指明新分支的最后一个commit
git rebase --onto <branchName> <from-commit-id>
变基这个新的分支到最终要合并到的分支,指明从哪个特定的commit开始
如: 还以上面的为例,假设你需要合并feature分支的commit 76cada ~62ecb3 到master分支。 首先需要基于feature创建一个新的分支,并指明新分支的最后一个commit:
git checkout -b <newbranch> 62ecb3
然后,rebase这个新分支的commit到master(–onto master)。76cada^ 指明你想从哪个特定的commit开始。
git rebase --onto master 76cada^
得到的结果就是feature分支的commit 76cada ~62ecb3 都被合并到了master分支。
在合并的过程中可能出现冲突,出现冲突,必须手动解决后,然后 运行
git add .
git rebase --continue
大小写敏感
如果你修改文件夹名(大写 → 小写 or 小写 → 大写),然后 git status 检测不到,这是因为 git 默认没开启大小写敏感,这时候需要全局开启。
设置本地git环境识别大小写: git config --global core.ignorecase false
重命名文件
直接使用以下命令重命名文件,在 git 中不要直接修改文件名,最好的办法是使用下面的方式
git mv -f [你想要删掉的文件] [你想要留下的文件]
git mv -f a.js A.js
等同于:
git rm a.js
git add A.js
修改文件夹名称
修改文件夹名称,全部改为大(小)写(F2重命名修改即可),然后push
到远程仓库。这时仓库上就会有重名的文件(文件夹)了。(大小写各一份)
然后需要删除多余的文件(文件夹),执行命令:
# 删除header文件夹下的所有文件
$ git rm --cached src/components/header -r
# 删除footer文件夹下的所有文件
$ git rm --cached src/components/footer -r
如果显示如下,说明操作成功:
rm 'src/components/header/index.js'
rm 'src/components/header/index.less'
...
然后同步,提交到远程仓库
# 添加在缓存
$ git add .
# 提交到本地
$ git commit -m'rm files'
# 提交到远程仓库 origin
& git push origin master
查看当前分支是从哪个分支check出来的?
在当前本地分支里,执行如下命令:
git log --oneline --graph --decorate
或者执行如下命令:
git reflog show 分支名
// git reflog --date=local | grep 分支名
仓库迁移保留commit和分支等信息
// 老仓库执行
git clone --bare https://xxx.git
cd xxx.git
// 在新的仓库创建空项目(什么都没有)
git push --mirror https://new-xxx.git
异常处理
处理大文件
如果分支中文件比较大的话,则需要安装 git lfs
其他
git推送到远程仓库时提示错误
remote: Incorrect username or password ( access token )
fatal: Authentication failed for 'https://gitee.com/***/***.git/'
解决方法:
清除本地仓库的用户名和密码:git config --system --unset credential.helper
再执行推送,重新输入用户名和密码
当我们对远程仓库里的文件进行了在线的修改,但是没有对本地库进行同步。
这个时候当我们再次用commit想要从本地库提交到远程库中时就会出现push失败的问题,错误信息:
error:failed to push some refs to https://gitee.com/***/***.git/
解决方法:
- 强推(不推荐):
git push -f
- 把远程库同步到本地库:
git pull --rebase
这条指令的意思是把远程库中的更新合并到本地库中,–rebase的作用是取消掉本地库中刚刚的commit,并把他们接到更新后的版本库之中。
简单来讲正常的解决冲突过程是:
1:git add *
2:git commit -m "XXX"
3:git push
时因为本地仓库代码与远程仓代码有冲突,所以接下来
4:git pull
拉取远程代码,而冲突需要手动解决
5:解决好后重新进行git add *
git commit -m "XXX"
git push
而如果git pull
这一步加上了--rebase
的选项,那么第5步操作将变成如下git add *
git rebase --continue
git push
评论区