git命令手册
参考文档:Git教程 | 菜鸟教程
原理图示意
1、超常用基础命令
1)初始化仓库 git init
需要切换到目标文件夹后执行命令,执行后会有一个.git(默认隐藏)的文件夹生成
git init
2)将工作区内容添加到暂存区
# 会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。
# 会把本地所有untrack的文件都加入暂存区,并且会根据.gitignore做过滤
git add .
# 仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。
# add -u 不会提交新文件(untracked file)。(git add --update的缩写)
git add -u
# 是上面两个功能的合集(git add --all的缩写)
git add -A
# 会忽略.gitignore把任何文件都加入
git add *
3)将暂存区的内容提交到本地仓库
# 将暂存区的内容生成一次commit,并且附带一个信息“message”
git commit -m [message]
# -a 参数设置修改文件后不需要执行 git add 命令,直接来提交。注意:只有修改的文件这样可以,新建的不行哦
git commit -a
4)拉取远程仓库代码到本地仓库 fetch/clone/pull
# 拷贝一个 Git 仓库到本地,让自己能够查看该项目,或者进行修改。
git clone [url] # [url] 是你要拷贝的项目。`git fetch # 前提是已经配置好了一个remote仓库,然后从远程仓库拉最新的一次提交到本地(只是拉下来,不进行合并等操作)
git pull # 将远端分支拉下来,并与当前的HEAD指针指向的commit进行合并
5)将本地仓库推送到远程仓库并合并 push
git push <远程主机名> <本地分支名>:<远程分支名>
# 如果本地分支名和远程的分支名是一致的,远程分支名可以省略
git push <远程主机名> <本地分支名>
# 如果本地版本与远程版本有差异,但又要强制推送可以使用 --force 参数:
git push --force origin master
首先使用remote将本地的链接到远端
git remote add github <仓库的ssh地址>
- 先将远端的仓库内容拉下来
git fetch <远端分支> <本地分支> # 将远端分支,拉到本地分支上
git checkout master
git merge github/master # 将github分支合并到master上,会报错
# 原因是github上边有一些文件是本地没有的,需要第一步先fetch
git merge --allow-unrelated-histories github/master # 添加允许两个毫不相关的分支进行合并
git pull # 相当于两步操作,拉下来新的改动,然后进行合并到当前工作区
- 再将本地的推到远端
git push github master # 将本地的master指向的最近一次commit提交到远端github分支上去
6)查看提交历史
git log # 查看历史提交记录。
git blame <file> # 以列表形式查看指定文件的历史修改记录。
# 用 --oneline 选项来查看历史记录的简洁的版本
git log --oneline
# --graph 选项来查看分支之间的变化
git log --graph --oneline
# 如果只想查找指定用户的提交日志可以使用命令:git log --author
git log --author=qsr --oneline -5 # 以单行的显示方式,查看qsr的最近5次提交
7)查看当前工作区和暂存区状态
git status
8)将本地仓库强行变基为远程仓库同步
等同于放弃本地所有的修改,强行与远程仓库同步
一般本地有一些文件与远程仓库出入较大,提交不上
git pull --rebase origin master
# 再进行提交
git push origin master
9)删除已经提交的文件/文件夹
比如.idea文件,提交的时候忘记忽略了,想删除
git pull origin master # 将远程仓库里面的项目拉下来
git rm -r --cached .idea # 删除.idea文件夹
git commit -m '删除.idea' # 提交,添加操作说明
git push -u origin master # 将本次更改更新到远程项目上去
2、如何解决冲突
场景:用户A、B都拉取了远程仓库的代码,同时对同一个文件内容进行了修改,A进行了push提交,此时B再push的时候就会失败,被远程仓库拒绝了,原因是有冲突,这个时候B用户该怎么办呢?
- 首先进行git pull,重新拉取远端仓库的内容和本地仓库进行合并
git pull
上图中告诉我们,将远程仓库拉下来之后由了冲突,我们需要解决冲突后才可以重新提交
- 解决冲突
vim index.html # 编辑我们的冲突文件
我们将其修改之后,进行保存
- 将此次改动进行add和commit
git add . # 将修改的内容添加至暂存区
git commit -am'解决index.html冲突' # 将此次提交定义为解决冲突的提交
3、分支管理
当你执行 git init 的时候,默认情况下 Git 就会为你创建 master 分支。
- 查看当前本地的所有分支情况
git branch
git branch -av # 查看所有分支,包括远程分支
- 创建分支
git branch [branchname] # 从当前HEAD指针处,创建新分支,branchname 为新的分支名称
git checkout -b [branchname] # 从当前HEAD指针处,创建新分支,并且切换到新分支上去
- 合并分支
git merge [newtest] # 将newtest分支合并到当前HEAD指向的分支
- 删除分支
git branch -d testing # 不能再testing分支上删除当前分支
# 优先使用 -d 因为会检查被删除的分支中是否还包含着未提交的内容
git branch -d <分支名>
# 如果 -d 参数删除不掉,说明有一部分是未提交的信息,想强行删除,可以使用-D
git branch -D <分支名>
- 切换分支
git checkout (branchname)
4、修改本地仓库的commit的message内容
1)修改最近一次的commit
git commit --amend
2)修改历史commit中的内容
# 我们首先需要明确,这个操作只是针对本地的操作
# 第一步需要进行变基
git rebase -i <commit号> # -i 打开交互信息,<commit要定位到,需要修改的父类对象处>
我们需要修改第二次提交的文本, :wq退出
紧接着弹出第二次提交的信息文档
进行修改后,wq保存并退出。
执行git log 查看,会发现第二次提交的信息已经被修改
git log
需要留意的是查看此次变基的影响
我们可以发现,修改了第二次提交的信息,这个地址编号也变了,后续的第三次提交也发生了变化。思考这是为什么呢?
因为我们修改了第二次提交的commit对象内容,这个对象内部的message对象进行了修改,整个commit内容也发生了修改
因为第三次提交的commit的对象,内部有一个tree对象,里边进一步包含第二次提交的tree内容
最终引发改了第二次,后续的所有对象都会跟着进行改变对象。
5、本地仓库,合并多个commit
1)合并连续的多个commit
同样的,我们需要将最近的三个commit合并的话,我们需要rebase到往前推的第四个。也就是需要做改动的前边一个父类
git rebase -i <commit号>
在交互文档中进行编辑,使用s标识合并,修改后的文件,将第三次和第四次进行合并
我们要知道,合并的意思是,将最近的几次提交合并到最近提交的那一个上,也就是 最近的这次不能改
如:
第五次提交、第四次提交、第三次提交、第二次提交、第一次提交
我们只能将二、三、四合并,通过rebase到第一次提交的地方,修改中间三次的command信息为s,意味着,将二、三、四合并到第五次提交中去。
简单的,如果标红,说明不允许对这个提交进行s操作
我们将其改回pick,并且wq退出,就会弹出新的交互页面
再次git log查看提交信息
会发现最近的一次commit的id号也发生了改变。本质是commit对象发生了变化
2)合并间隔的几个commit
我们想把‘第六次的提交’和第一个进行合并
变基
git rebase -i 16a6793296ad7f344492e90768dd5b9dd714eff1 # 将HEAD指向最早的那个commit处
- 打开发现只有两个,我们需要手动添加进去第一个提交内容
2. 将需要合并的‘第六次提交’移到第二行,和第一次提交的内容靠在一起
- 将多余的那个最后一行删除,并且修改命令为s
- 保存并退出,弹出如下错误,不要怕,看看git status中显示什么?
- 执行 git status
- 执行git rebase --continue
6、暂存区内容、HEAD内容、工作区内容对比
1)暂存区和HEAD内容进行比较
git status # 查看暂存区和工作区文件级别的差异
git diff --cached # 查看暂存区的文件内容,和HEAD指针指向的那次提交内容的差异(并非是当前工作区)
我们将1.txt文件中新加了一些内容,并且通过git add 提交到了暂存区,这时我们要对比的是暂存区和当前HEAD指针指向的那次提交,之间的差异。使用的是git diff --cached
2)暂存区内容和工作区内容进行比较
git diff # 比较暂存区和工作区的内容
我们继续修改1.txt,将1111内容删除掉,不需要提交到暂存区
我们发现红色表示已经删除的内容,也就是说,我们工作区已经没有这个内容了,但是暂存区还有
7、将工作区内容重置为暂存区内容
现在我们的暂存区是什么样子的呢?git status看一下
工作区中又对1.txt进行了改动,如何恢复暂存区内容到工作区呢?
git checkout -- 1.txt # 将暂存区中1.txt文件内容还原到工作区中来
最后一步查看,发现工作区中没有任何变化
8、将暂存区内容重置为HEAD内容
我们需要清空暂存区,保持暂存区和HEAD指针指向的commit保持一致
git reset HEAD
可以看到暂存区没有内容,只有工作区的两个文件还在,并且显示没有被add到暂存区
9、取消暂存区中的部分文件修改
我们可以看到当前暂存区有两个文件的更改,我们只想保留1.txt继续在暂存区,2.txt需要还原为HEAD指向的commit内容一样
git reset HEAD -- <file1> <file2> ... # 将暂存区中的file1、file2 ... 还原到HEAD指针中的内容
10、撤销最近的几次提交
最安全的撤销,传送门:阮一峰:如何撤销Git操作
$ git revert HEAD
# $ git revert [倒数第一个提交] [倒数第二个提交]
# --no-edit:执行时不打开默认编辑器,直接使用 Git 自动生成的提交信息。
# --no-commit:只抵消暂存区和工作区的文件变化,不产生新的提交。
接下来是不太安全的撤销
我们彻底不想要最近的2次提交内容了
我们需要执行
git reset --hard <commit的id> # 将头指针指向某一次提交,其他的提交完全抛弃
悄咪咪问:有后悔药吃吗?
其实是有的。只要我们还能尽快找到当时的那次提交id号,(在git销毁之前还原)
11、比较两个分支中的某一个文件的差异
git diff <分支1> <分支2> -- <文件名> # 比较分支1和分支2中某一个文件的内容差异
# 分支2中新增的,会标记成绿色 + 号
# 分支其实就是一个指针,指向的是这次分支的最近一次提交内容,换成对应的提交id号是一样的效果
12、工作区临时保存,stash
git stash # 将当前工作区内容进行临时保存到stash列表中
git stash list # 查看当前stash列表信息有哪些
git stash apply # 恢复当前工作区内容,stash列表中还仍然保留着这个信息
git stash pop # 恢复当前工作区内容,stash列表中就不再继续存储这个工作区内容
13、.gitignore文件
添加.gitignore
文件,文件内容规则简单
*.txt # 表示忽略所有以.txt结尾的文件
*.abc/ # 表示所有以.abc结尾的文件夹和里边的所有文件都将被忽略
# 但是如果有.abc结尾的文件,是可以被git管控的
14、将远程仓库备份到本地
我们就用刚才的本地仓库,当成远端,我们来进行备份,备份方式有几种协议。
前边两种一般都是本地的进行备份的时候进行使用,下边两种是远端,公共仓库进行备份使用的
mkdir backup-test # 创建一个备份文件夹,不能在工作区中
git clone --bare E:/gitDemo/code_file/.git ya.git # 哑协议用法,取名为ya.git文件
git clone --bare file://E:/gitDemo/code_file/.git zhineng.git # 智能协议用法,取名为zhineng.git文件
我们现在在备份文件夹中就有了一个完全一样的备份,此时我们将两个文件夹当成,一个本地,一个是远端,我们之前操作的文件夹为远端仓库。
15、多人协作常见的几个场景
1)Git集成的使用禁忌
- 禁止向集成分支执行
git push -f
操作
会将远程仓库的内容强制同步为本地仓库的内容,如果本地仓库进行过了重置操作,这个“重置”,如果使用git push -f 也会将远端的内容搞没。
- 禁止向集成分支执行变更历史(变基)的操作
会让其他人push的时候报错。禁止在集成分支变基,需要在原有的远程分支基础上一步步改进
2)不同人修改了不同文件如何处理?
当你push的时候提示:
这时候,我们需要先fetch,然后merge(或者直接pull),合并改动后,再进行提交。完事。
3)不同人修改了同文件的同一区域如何处理?
这就是冲突,需要解决冲突,参考本文中,如何解决冲突。
4)不同人修改了同文件的不同区域如何处理?
不需要额外多做其他工作,git会自动识别,并且帮我们进行merge,提交前注意先pull,再push就行
5)把同一文件改成了不同的文件名如何处理?
我们如果修改了index.html,为index1.html,而远端已经有人提交了修改这个文件的名称为index2.html
当我们git pull的时候,会在暂存区有三个相同内容的文件,git将其视为冲突,需要解决
暂存区会有三个文件
我们执行
git rm index.html
git rm index2.html
# 最终保留index1.html文件
这个时候我们再执行commit和push操作就可以了
6)合并分支中的某一些提交 - “采草莓”场景
cherry-pick讲解,原文传送门:阮一峰 git cherry-pick教程
- 基本使用
git cherry-pick
命令的作用,就是将指定的提交(commit)应用于其他分支。
git cherry-pick <commitHash>
上面命令就会将指定的提交commitHash
,应用于当前分支。这会在当前分支产生一个新的提交,当然它们的哈希值会不一样。
举例来说,代码仓库有master
和feature
两个分支。
a - b - c - d # Master
\
e - f - g # Feature
现在将提交f
应用到master
分支。
# 切换到 master 分支
$ git checkout master
# Cherry pick 操作
$ git cherry-pick f
上面的操作完成以后,代码库就变成了下面的样子。
a - b - c - d - f # Master
\
e - f - g # Feature
从上面可以看到,master
分支的末尾增加了一个提交f。
git cherry-pick
命令的参数,不一定是提交的哈希值,分支名也是可以的,表示转移该分支的最新提交。
$ git cherry-pick feature
上面代码表示将feature
分支的最近一次提交,转移到当前分支。
- 转移多个提交
Cherry pick
支持一次转移多个提交。
$ git cherry-pick <HashA> <HashB>
上面的命令将 A
和 B
两个提交应用到当前分支。这会在当前分支生成两个对应的新提交。
如果想要转移一系列的连续提交,可以使用下面的简便语法。
$ git cherry-pick A..B
上面的命令可以转移从 A
到 B
的所有提交。它们必须按照正确的顺序放置:提交 A
必须早于提交 B
,否则命令将失败,但不会报错。
注意,使用上面的命令,提交 A 将不会包含在 Cherry pick
中。如果要包含提交 A
,可以使用下面的语法。
$ git cherry-pick A^..B
- 配置项
git cherry-pick
命令的常用配置项如下。
(1)-e
,--edit
打开外部编辑器,编辑提交信息。
(2)-n
,--no-commit
只更新工作区和暂存区,不产生新的提交。
(3)-x
在提交信息的末尾追加一行(cherry picked from commit …),方便以后查到这个提交是如何产生的。
(4)-s
,--signoff
在提交信息的末尾追加一行操作者的签名,表示是谁进行了这个操作。
(5)-m parent-number
,--mainline parent-number
如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick
默认将失败,因为它不知道应该采用哪个分支的代码变动。
-m
配置项告诉 Git
,应该采用哪个分支的变动。它的参数parent-number
是一个从1开始的整数,代表原始提交的父分支编号。
$ git cherry-pick -m 1 <commitHash>
上面命令表示,Cherry pick
采用提交commitHash
来自编号1的父分支的变动。
一般来说,1号父分支是接受变动的分支(the branch being merged into),2号父分支是作为变动来源的分支(the branch being merged from)。
- 如果操作过程中发生代码冲突,
Cherry pick
会停下来,让用户决定如何继续操作。
(1)--continue
用户解决代码冲突后,第一步将修改的文件重新加入暂存区(git add .),第二步使用下面的命令,让 Cherry pick 过程继续执行。
$ git cherry-pick --continue
(2)--abort
发生代码冲突后,放弃合并,回到操作前的样子。
(3)--quit
发生代码冲突后,退出 Cherry pick
,但是不回到操作前的样子。
- 转移到另一个代码库
Cherry pick
也支持转移另一个代码库的提交,方法是先将该库加为远程仓库。
$ git remote add target git://gitUrl
上面命令添加了一个远程仓库target。
然后,将远程代码抓取到本地。
$ git fetch target
上面命令将远程代码仓库抓取到本地。
接着,检查一下要从远程仓库转移的提交,获取它的哈希值。
$ git log target/master
最后,使用git cherry-pick
命令转移提交。
$ git cherry-pick <commitHash>