Git是一个极其优秀的分布式版本控制系统。该系统可以记录用户文件的每一次变动,还具有强大的团队协同工作能力,每个人都可以提交对文本的改动,而不必担心会覆盖他人的操作。Github更是一个通过Git进行版本控制的软件源代码托管服务。截至到2015年,Github已经有超过九百万注册用户和2110万代码库。Github已经成为了世界上最大的代码存放网站和开源社区。
GIT使用教程
创建版本库
选择一个合适的地方,创建一个空目录
1 | mkdir <dir-name> |
之后会在当前目录下产生一个.git的目录,该目录是Git用来跟踪管理版本库,也可以选用一个非空目录创建Git仓库
编写保存文件
编写文件并存放至<dir-name>
目录下(或子目录)
用纯文本方式编辑并保存文件,文件编码格式保存为UTF-8编码格式
1 | git add <filename1> <filename2> ... #告知Git将文件添加至仓库 |
Git中,用HEAD表示当前版本,上一版本就是HEAD,上上版本为HEAD^,往上N个版本可写为HEAD~N
1 | git reset --hard <fileID> #文件版本跳至版本ID为<fileID>的文件 |
工作区与暂存区
工作区
在计算机里可以看到的目录就是工作区,用于存放文件
版本库与暂存区
工作区下有一个隐藏目录.git,这个是git的版本库,版本库里存有暂存区(stage/index)
Git大致工作原理
文件添加至Git版本库分为两步:
git add
将文件添加进暂存区,即把对文件的修改或相关操作添加到暂存区git commit
提交更改,即把暂存区的全部内容提交到当前分支
文件撤销操作
$ git checkout -- <filename>
将--
很重要,没有--
就变成了切换到另一个分支的命令
文件撤销情况
关于文件需要撤销操作的,大致有两种情况: +
<filename>
自修改后还没放到暂存区,则命令执行后文件撤销修改就回到和版本库一模一样的状态
+
<filename>
已经添加到暂存区后,又作了修改,则命令执行后文件撤销修改就回到添加到暂存区后的状态
总之,就是让文件回到最近一次git commit
或git add
时的状态
撤销与回退小结
- 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- <filename>
- 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步:用命令
git reset HEAD <filename>
,就回退到1中,然后继续1的操作 - 当你已经提交了不合适的修改到版本库时,想要撤销本次提交,可参考版本回退,不过前提时没有推送到远程库
版本回退:git reset --hard <ID>
,将文件跳至版本号ID的文件,HEAD表示最新的文件版本
Git撤销删除
Git中删除也是一种修改操作
一般情况下,在提交至版本库后,我们直接在文件管理器中删除文件(或通过rm
命令),git status
会告知那些文件被删除,这时有两种选择:
1.
确实要从版本库中删除,可执行git rm
命令删除,并git commit
2.
手误删除文件,这时可执行git checkout -- <filename>
命令把误删的文件恢复到最新版本
*
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以"一键还原",
命令git rm
用于删除一个文件,如果一个文件已经被提交到版本库,那永远不用担心误删,但你只能恢复文件到最新版本,你会丢失最近一次修改提交后的内容
创建SSH Key
1 | ssh-keygen -t rsa -C "youremail@example.com" |
创建后,可在用户主目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个文件就是SSH Key
的秘钥对,id——rsa
是私钥,不能泄露,id_rsa.pub
是
公钥,可以公布。之后登陆Github进行设置,进入"SSH Key"页面,点击"Add SSH
Key",填上任意标题,在Key文本框里粘贴id_rsa.pub
文件里的内容
Github允许添加多个Key
关联远程库
首先在Github上新建一个仓库(或者使用已有的仓库),在本地的一个仓库中运行以下命令:
1 | git remote add origin git@github.com:<accountname>/<localreponame>.git |
添加后,远程库名字Git默认为origin,可以更改:
1 | git push -u origin master |
git push命令,实际是把当前分支master推送到远程,
如果这是你第一次推送master分支,你需要加上-u参数,Git不但会把本地的master分支内容推送到远程的新的master分支,还会把本地的master分支和远程的master分支关联起来,
在以后的推送或者拉取时可简化命令,之后只要本地作了提交,就可以通过命令:$ git push origin master
完成提交
在第一次使用Git的clone
或push
命令时会得到一个SSH警告,输入yes即可
1 | 关联一个远程库 |
克隆远程库到本地
在Github中新建库后,可以使用git clone
克隆一个本地库
$ git clone git@github.com:<git库地址>
Git支持多种协议,包括https
windows系统:$ git clone <Git远程库的url>
Git分支
1 | git branch #查看分支 |
多个分支是共用暂存区,即如果在分支1上仅add而不commit,实际暂存区中已经记录该次修改,哪怕之后切换到分支2上再进行commit也是有效操作
当Git无法自动合并分支时,需要首先解决冲突。解决冲突后再提交,
用git log --graph
命令可以看到分支合并图,git status
也可以查看冲突的文件
e.g:$ git log --graph --pretty=oneline --abbrev-commit
Git分支管理
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出曾经做过合并,而fast-forward合并就看不出曾经做过合并
1 | git merge --no-ff -m"..." <name> |
以普通方式合并分支(即禁用fast forward)因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去`
分支策略:
- 在实际开发中,我们应该按照几个基本原则进行分制管理:
- master分支应该是非常稳定的,也就是仅用来发布新版本,平时不在上面干活;
- 干活都在dev分支,即devd分支是不稳定的,到某个时候,再把dev分支合并到master分支上;
- 每个人都在dev分支上工作,每个人都有自己的分支,要保存时往dev分支上合并就可以了
Bug分支
$ git stash
命令相当于对当前工作环境做一个快照,等以后恢复环境后继续工作
在哪个分支上修复bug,就在从哪个分区创建临时分支
修复完后再提交并删除分支
1 | git stash list #查看是否存在stash |
修复Bug时,当手头工作没有完成时,先把工作现场git stash
一下,然后再去修复Bug,修复后,再git stash pop
回到工作现场
Feature分支(添加新功能)
在开发新功能时最好新建一个分支,
若要丢弃一个没有被合并过的分支,可以通过git branch -D <name>
强行删除
多人协作
$ git remote
查看远程库的信息
$ git remote -v
查看远程库详细的信息(上面显示了抓取和推送的<远程库名字>的地址,如果没有推送权限,就看不到push的地址)
- 推送分支:
推送分支就是把该分支上的所有本地提交推送远程库。推送时,要指定本地分支
1 | git push <远程库名字> <本地库名字> |
抓取后在本地合并并解决冲突后再推送
- 工作模式:
- 首先,可以试图用
git push origin branch-name
推送自己的修改 - 如果推送失败,则因为远程分支比你的本地版本新,需要先用
git push
试图合并 - 如果合并有冲突,则解决冲突,并在本地提交
- 没有冲突或者解决掉冲突后,再用
git push origin branch-name
推送就能成功
如果git pull
提示"no tracking
information",则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name
(该命令用于建立本地分支和远程分支的关联)
标签管理
发布一个版本时,我们通常先在版本库中打一个标签tag,这样,就唯一确定了打标签时的版本。在将来的某个时候,取某一个标签的某一版本,就是把那个打标签的时刻对应的版本取出。标签也是版本库的一个快照
Git标签虽然是版本库的快照,但其实它是指向某个commit的指针(分支可以移动,标签不能移动)
Tag就是一个让人容易记住的名字,它与某个commit绑定在一起
1 | git tag <name> #在git中打标签应先切换至需要打标签的分支 |
标签不是按时间顺序列出,而是按字母排序的,可以用git show <tagname>
查看标签信息
1 | git tag -a <tagname> -m "..." #创建带说明的标签,-a指定标签名,-m指定说明文字 |
其中在上面第一行代码中若用参数-s替换-a则可以用PGP签名标签
已推送到远程的标签的删除:
1 | git push <远程库名字> :refs/tags/<tagname> |
在Github上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送Pull request给他人仓库来贡献代码;
Fork他人仓库之后再在自己的账号下clone仓库,这样才能推送修改
自定义Git
1 | git config --global color.ui true #git会适当显示不同的颜色 |
- 忽略文件
在Git工作区的根目录下有一个.gitignore文件(没有可创建),然后把要忽略的文件名填进去,Git就会自动忽略这些文件
忽略文件的原则:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是一个文件通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库;
- 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件
之后将.gitignore也提交到Git,就完成了忽略文件设置
1 | git check-ignore #检查.gitignore文件 |
我们可以对.gitignore进行版本管理
- 设置别名
$ git config --global alias <别名> <命令原名>
--global参数是全局参数,也就是这些命令在电脑的所有Git仓库下都有效
配置Git时,加上--global
是针对当前用户启作用,如果不加,则只针对当前仓库起作用。
每个仓库的Git配置文件都放在.git/config文件中,
别名在[alias]后面,删除别名则直接删除对应行即可。
当前用户的Git配置文件在用户主目录的一个隐藏文件.gitconfig中
搭建Git服务器(linux ubuntu or debian)
- 安装git:
$ sudo apt-get install git
; - 创建一个git用户,用来运行git服务:
$ sudo adduser git
; - 创建证书登录:收集所有需要登录的用户的公钥,即他们的id_rs.pub文件,将所有公钥导入到/home/git/.shh/authorized_keys文件中(可改名);
- 初始化Git仓库:
$ sudo git init --bare <reponame>
;参数--bare为创建一个裸仓库,即没有工作区(服务器上的Git仓库通常都以.git结尾,创建后把owner改为git$ sudo chown -R git:git <reponame>
; - 禁用shell登录:出于安全考录,2中创建的git用户不允许登录shell,可通过编辑/etc/passwd文件实现
找到类似一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:git:x:1001:1001:,,,:/home/git:/usr/bin/got-shell
这样当用户用shell登录时会自动退出; - 克隆远程仓库:
$ git clone git@server:/srv/<reponame>
;在各自的电脑中运行
致谢:
廖雪峰的Git教程(转载请保留连接)