Git教程
Git是目前世界上最先进的分布式版本控制系统
安装
[Git for Windows](https://github.com/waylau/git-for-win)
- 然后默认安装
- 配置 :
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
创建版本库
版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
$ mkdir learngit
创建一个learngit目录
$ cd learngit
$ pwd
/Users/michael/learngit
- 通过git init命令把这个目录变成Git可以管理的仓库
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
- 添加文件到Git仓库,分两步:
- 使用命令git add ,注意,可反复多次使用,添加多个文件;
- 使用命令git commit -m ,完成。
时光机穿梭
git status
命令可以让我们时刻掌握仓库当前的状态git diff 文件名
查看修改的内容git add 文件名
添加修改的内容到仓库git status
查看状态git commit -m 描述修改内容
提交修改的内容到仓库git status
查看仓库的当前状态
版本回退
git log
查看最近3次提交的版本git log --pretty=oneline
列出版本的commit id(版本号)- HEAD表示当前版本 上个版本是HEAD^ 向上100个版本是HEAD~100
git reset --hard HEAD^
回退上个版本cat readme.txt
查看readme.txt的内容git reset --hard 版本id
退到指定的版本仓库git reflog
用来记录你的每一次命令,可以查找新版的id
工作区和暂存区
- 前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
- 第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
- 第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
- 你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
管理修改
- 第一次修改 -> git add -> 第二次修改 -> git commit
- 你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别:- 你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
- 第一次修改 -> git add -> 第二次修改 -> git add -> git commit
撤销修改
git checkout -- 文件名
可以丢弃工作区的修改- 命令
git checkout -- readme.txt
意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况: - 一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
- 一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
git checkout -- file
命令中的–很重要,没有–,就变成了“切换到另一个分支”的命令git reset
命令既可以回退版本,也可以把暂存区的修改回退到工作区。
删除文件
$ rm 文件名
删除文件- 现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:
git rm 文件名
git commit -m "remove 文件名"
- 另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
git checkout -- test.txt
- 注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!
远程仓库
添加远程仓库
- GitHub创建SSH连接: Setting ==> SSH and GPG keys ==> News SHH key ==>复制id_rsa.pub到key
- GitHub创建仓库:Repositories ==>…
- 我们勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。
- 本地与GitHub建立连接:
git remote add origin ssh/https连接地址
- 关联后,使用命令
git push -u origin master
第一次推送master分支的所有内容; - 此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master
推送最新修改;
从远程仓库克隆
git clone 资源地址
- 使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
- Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
分支管理
创建与合并分支
git checkout -b dev
创建分支dev并切换到分支dev 相当于git branch dev
,git checkout dev
git branch
命令会列出所有分支,当前分支前面会标一个*
号。- 在dev分支上做修改,
git add readme.txt
;git commit -m "add readme.txt"
;在master分支上是没有变化的,要合并; git checkout master
切换到master分支;* master
git merge dev
把dev分支的工作成果合并到master分支上git branch -d dev
删除dev分支- 现在master分支上已经有dev分支整合过来的内容了
switch
- 我们注意到切换分支使用
git checkout <branch>
,而前面讲过的撤销修改则是git checkout -- <file>
,同一个命令,有两种作用,确实有点令人迷惑。 - 实际上,切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:
- 创建并切换到新的dev分支,可以使用:
git switch -c dev
- 直接切换到已有的master分支,可以使用:
git switch master
- 使用新的git switch命令,比git checkout要更容易理解。
解决合并冲突
- 当master分支和新建的分支dev都有新的提交时就会产生冲突
- Git用
<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容 - Git告诉我们,readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件 *** 手动修改然后添加提交 ***
- 然后删除分支
git branch -d 分支名
- 查看合并图
git log --graph
;git log --graph --pretty=oneline --abbrev-commit
分支管理策略
- 合并分支时,如果可能,Git会用
Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息 - 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
- 准备合并dev分支,请注意
--no-ff
参数,表示禁用Fast forward
:git merge --no-ff -m "merge with no-ff" dev
Bug分支
- Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
git stash
- 工作区是干净的,刚才的工作现场存到哪去了?用
git stash list
命令看看: - 工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
- 一是用
git stash apply stash名字
恢复,但是恢复后,stash内容并不删除,你需要用git stash drop
来删除; - 另一种方式是用
git stash pop
,恢复的同时把stash内容也删了: - 如果要丢弃一个没有被合并过的分支,可以通过
git branch -D <name>
强行删除。
多人协作
- 要查看远程库的信息,用
git remote
git remote -v
显示更详细的信息:git push origin master
推送master分支;git push origin dev
推送dev分支git clone ssh/https地址
克隆抓取分支- 当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支
- 因此,多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin <branch-name>
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功! - 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令
git branch --set-upstream-to <branch-name> origin/<branch-name>
。 - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull抓取远程的新提交; - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
; - 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。 git rebase
操作可以把本地未push的分叉提交历史整理成直线;
标签管理
- 在Git中打标签非常简单,首先,切换到需要打标签的分支上,然后,敲命令
git tag <name>
就可以打一个新标签 - 可以用命令
git tag
查看所有标签: - 之前忘记打标签了,可以
git tag <name> conmmit的id
- 用
git show <tagname>
查看标签信息: - 还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
git tag -a <tagname> -m "version 0.1 released" conmmit的id
- 删除标签
git tag -d <tagname>
- 如果要推送某个标签到远程,使用命令
git push origin <tagname>
: - 一次性推送全部尚未推送到远程的本地标签
git push origin --tags
- 删除远程的标签:首先删除本地
git tag -d <tagname>
,然后删除远程git push origin :refs/tags/<tagname>
自定义Git
- Git显示颜色
git config --global color.ui true
- 忽略某些文件时,需要编写
.gitignore
; .gitignore
文件本身要放到版本库里,并且可以对.gitignore做版本管理!git config --global alias.st status
配置别名- 配置Git的时候,加上–global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
搭建Git服务器
- 安装git:
sudo apt-get install git
- 创建一个git用户,用来运行git服务:
sudo adduser git
- 创建证书登录:收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个
- 初始化Git仓库:
sudo git init --bare sample.git
- …