Git (分布式版本控制系统)
此文为在参考 廖雪峰教程(即下文推荐网址第一个),整理的笔记,非常喜欢廖雪峰老师写的教程,非常仔细易懂,终于不再一脸懵逼了
推荐网址
本地仓库
创建仓库(repository)
1.创建目标文件夹
mkdir target
cd target
pwd. // 显示当前目录
2.将目标文件夹变成Git可管理的仓库(这是本地仓库)
git init
此时,该文件夹下将多一个 .git
的目录(隐藏的),即Git用来跟踪管理版本库,不可随意修改 (当然可以直接删除这个目录使目标文件夹的内容不再受Git管理)
提交目标文件(夹)到仓库
将目标文件,如readme.txt
放到Git仓库
git add readme.txt
git commit -m "first commit"
git add
告诉Git把文件(夹)添加到仓库, 可反复使用,添加多个
git commit
告诉Git将文件提交到仓库
目标文件修改后
1.查看目标文件修改状态
假如对readme.txt
文件内容进行了修改,那么在当前目录下执行以下命令
git status
git status
列出仓库的当前状态(增删改)
2.查看目标文件修改内容
git diff readme.txt
git diff
顾名思义即查看difference,可以通过该命令查看目标文件修改的内容
3.提交修改的目标文件到仓库(与提交新文件相同)
git add readme.txt
git commit -m "second commit"
版本回滚
1. 查看历史记录
git log
显示的是从最近到最远的提交日志,如果嫌弃输入信息过多,可加上 --pretty=oneline
参数,比如
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 third commit
ea34578d5496d7dd233c827ed32a8cd576c5ee85 second commit
cb926e7ea50ad11b8f9e909c05226233bf755030 first commit
其中,一大串数字362816...882e1e0
是提交的版本ID,一个SHA1计算出来的十六进制数字
2.回滚上一个版本
在Git中,当前版本用HEAD
表示,上一个版本是HEAD^
, 上上个版本是HEAD^^
,以此类推,往上100个版本可以写成HEAD~100
假如,现在要把当前版本 third commit
回滚到上一个版本 second commit
,可使用git reset
命令
git reset --hard HEAD^
3.回到未来版本
如果此时用git log
查看历史记录是已经找不到third commit
的,但是如果还想回到third commit
版本. (版本号可不必写全)
a. 只要上面命令行窗口未关闭,找到这个版本的
commit ID
(版本号)git reset --hard 3628164
b. 如果关闭了,那么可以用
git reflog
,记录了你的每一次命令$ git reflog ea34578 HEAD@{0}: reset: moving to HEAD^ 3628164 HEAD@{1}: commit: third commit ea34578 HEAD@{2}: commit: second commit cb926e7 HEAD@{3}: commit (initial): first commit
第二行显示的
third commit
的commit ID 是3628164
,然后执行a
中的命令即可
工作区与暂存区
工作区
在电脑中可看到的目录
版本库(repository)
工作区的隐藏目录.git
,即Git用来跟踪管理版本库的,不算工作区
如上图(来自廖雪峰教程图),版本库中有个叫stage
(或者index
)的暂存区,自动创建的第一个分支master
,以及指向master
的一个指针HEAD
当我们使用git add
把文件添加进去,实际上是添加到暂存区;
当我们使用git commit
提交更改时,实际上是把暂存区的所有内容提交到当前分支
撤销修改
1. 撤销的修改内容在工作区
git checkout -- readme.txt
- a. 如果该文件自修改后还没
git add
,即还未放到暂存区,那么,撤销修改后回到和版本库一样的状态; - b. 如果该文件已添加到暂存区,又在工作区做了修改,那么撤销修改后回到添加到暂存区后的状态
2. 撤销的修改内容在暂存区
git reset HEAD readme.txt
git checkout -- readme.txt
git reset HEAD readme.txt
可以把暂存区的修改撤销掉,重新放回到工作区,HEAD
表示最新的版本, 然后再把工作区的内容撤销
3. 撤销的修改内容在版本库
那么见上面所说的回滚版本
删除文件
一般情况下,在电脑里将某些文件删了,或者用rm
命令删除,此时工作区和版本库不一致了
1. 确定需要从版本库中删除该文件
git rm readme.txt
git commit -m "remove readme.txt"
2. 删错了,可从版本库中恢复到最新版本
git checkout -- readme.txt
远程仓库
添加远程仓库
1.同步本地与远程仓库
在本地已经创建一个Git仓库后,再在远程创建一个仓库,将这两个仓库关联在一起,则,可以在本地仓库根目录下命令
git remote add origin xxxxxx
xxxxxx
为远程仓库地址,可以是 git
协议 也可以是 https
协议 ,但通过ssh
支持的原生git
协议最快
远程仓库的名字机会说origin
,这是Git默认的叫法
2.将本地仓库的所有内容推送到远程仓库
git push -u origin master
实际上是把当前分支master
推送到远程,由于远程仓库是空的,第一次推送时加上了-u
参数
3.本地修改提交后推送到远程仓库
git push origin master
把本地master
分支的最新修改推送到远程仓库
从远程仓库克隆
假如一开始先创建远程仓库,那么可以在本地直接通过git clone
命令将远程仓库内容克隆到本地,假如远程仓库地址为xxxxxx
git clone xxxxxx
分支
1.创建分支dev
,然后切换到dev
分支
git checkout -b dev
git checkout
加上-b
参数表示创建并切换,相当于以下两条命令:
git branch dev
git checkout dev
2.查看当前分支
$ git branch
* dev
master
git branch
命令会列出所有分支,当前分支前面会标一个*
号
3.合并分支,将分支dev
合并到master
git checkout master
git merge dev
git merge
命令用于合并指定分支到当前分支
4.删除分支
git branch -d dev
解决冲突
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
用git log --graph
命令可以看到分支合并图
分支策略
强制禁用Fast forword
模式
git merge --no-ff -m "merge with no-ff" dev
合并分支,加上--no-ff
参数可用普通模式合并,合并后的历史有分支,而fast forward
合并看不出合并过
因为本次合并要创建一个新的commit
,所以加上-m
参数,把commit描述写进去
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活
干活都在dev
分支,即,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本
Bug分支
理解:暂存区和工作区是公用的,多个分支公用,如果不先add, commit 就会带到切换到的另一个分支
而git stash
只是隐藏暂存区的内容
1.将暂存区隐藏
git stash
当在dev
分支的修改还未提交,但是又需要在master
分支,再建一个分支来修复bug, 那么可以使用git stash
来将暂存区的修改内容隐藏,再建立新的分支
此时,用git status
命令查看是干净的
2. 查看刚刚隐藏的暂存区
git stash list
3. 恢复的暂存区
// a 方法
git stash apply
git stash drop
// b 方法
git stash pop
git stash apply
恢复,stash内容不删除,需要git stash drop
删除
git stash pop
恢复的同时把stash内容也删除了
Feature分支
强行删除未合并的分支
git branch -D feature
开发一个新feature,最好新建一个分支
如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除
多人协作
1.查看远程库信息
git remote
git remote -v
添加-v
参数可以看到更详细的信息
当从远程库clone时,实际上是把本地的master
分支和远程库的master
分支对应起来了,远程库默认名称是origin
2.推送分支
git push origin master
推送分支,就是把该分支上的所有本地提交推送到远程库,推送时,要指定本地分支
推送分支的一般原则:
master
分支是主分支,需与远程库同步
dev
分支是开发分支,团队开发分支,也需同步
bug分支修复bug,没必要
feature分支看是否多人合作
3.在本地创建和远程分支对应的分支,如 origin
的dev
分支
git checkout -b dev origin/dev
4.拉取分支
git pull
如果推送分支失败,说明远程库分支比你本地的更新,需要先拉取pull
合并,如果有冲突,解决冲突,并在本地提交,最后,再推送push
5.建立本地分支和远程分支的关联
如果git pull
提示no tracking information
说明本地分支和远程分支的链接关系没有创建,可以用如下命令
git branch --set-upstream branch-name origin/branch-name
标签 Tag
标签是版本库的快照,指向某个commit的指针(分支可以移动指针,标签不可以)
创建标签
1.在当前分支,创建新的标签
git tag v1.0
2.创建历史提交的commit的标签
默认标签是打在最新提交的commit上,即HEAD
,如果是打历史版本的,可以找到历史提交的commit id, 再打,比如:
$ git log --pretty=oneline --abbrev-commit
6a5819e merged bug fix 101
cc17032 fix bug 101
7825a50 merge with no-ff
...
比如,需要对 commit id 是 cc17032 打标签
git tag v0.9 cc17032
3.创建带有说明的标签
git tag -a v0.1 -m "version 0.1 released" 3628164
-a
指定标签名,-m
指定说明文字
4.查看所有标签(按字母排序)
git tag
5.查看某个标签的具体信息
git show v0.9
6.使用PGP签名标签
git tag -s v0.2 -m "signed version 0.2 released" fec145a
-s
用私钥签名一个标签
签名采用PGP签名,因此必须先安装gpg(GnuPG)
操作标签
1.删除标签
git tag -d v0.1
2.推送标签到远程库
git push origin v1.0
3.一次性推送所有的未推送的本地标签
git push origin --tags
4.删除远程标签
git tag -d v0.9
git push origin :refs/tags/v0.9
需要先在本地删除,再推送到远程库,但格式如上
自定义Git
忽略特殊文件
忽略文件原则:
- 忽略系统自动生成的文件,比如缩略图
- 忽略编译生成的中间文件、可执行文件
- 忽略自己带有敏感信息的配置文件
1.在工程目录下创建.gitignore
文件
具体忽略文件内容可查看GitHub的配置文件,链接为 gitignore
2.强制添加被忽略的文件
git add -f xx.txt
3.检查.gitignore
文件规则写错
git check-ignore -v xx.txt
配置别名
1.给git命令配置别名,例如
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.unstage 'reset HEAD'
--global
参数是全局参数,即这些命令可在这台电脑的所有Git仓库使用
从此,st
就表示status
,co
表示checkout
,ci
表示commit
,br
表示branch
,unstage
表示reset HEAD
2.配置文件
加上--global
参数是针对当前用户起作用,不加,则只针对当前仓库起作用
每个仓库的Git配置文件在.git/config
而当前用户的Git配置文件在用户主目录下的.gitconfig