Git是一个极其优秀的分布式版本控制系统。该系统可以记录用户文件的每一次变动,还具有强大的团队协同工作能力,每个人都可以提交对文本的改动,而不必担心会覆盖他人的操作。Github更是一个通过Git进行版本控制的软件源代码托管服务。截至到2015年,Github已经有超过九百万注册用户和2110万代码库。Github已经成为了世界上最大的代码存放网站和开源社区。
GIT使用教程
创建版本库
选择一个合适的地方,创建一个空目录
mkdir <dir-name>
cd <dir-name> #在仓库中进行操作
pwd #可查看当前目录
git init #将目录变为Git可以管理的仓库,即初始化仓库
之后会在当前目录下产生一个.git的目录,该目录是Git用来跟踪管理版本库,也可以选用一个非空目录创建Git仓库
编写保存文件
编写文件并存放至<dir-name>目录下(或子目录)
用纯文本方式编辑并保存文件,文件编码格式保存为UTF-8编码格式
git add <filename1> <filename2> ... #告知Git将文件添加至仓库
git commit -m "..." #将文件提交到仓库 -m后面输入本次提交的说明,可以一次提交多个文件
git status #可查看仓库当前的状态,告知用户是否有文件被修改
git diff #查看文件具体修改了什么,或对比文件
git log #显示从最近到最远的提交日志(可加上参数--pretty=oneline改变显示视图)
git reset --hard HEAD^ #文件回退至上一版本
Git中,用HEAD表示当前版本,上一版本就是HEAD^,上上版本为HEAD^^,往上N个版本可写为HEAD~N
git reset --hard <fileID> #文件版本跳至版本ID为<fileID>的文件
git reflog #记录用户的每一次操作,可借由此查看文件回退前的版本号
工作区与暂存区
工作区
在计算机里可以看到的目录就是工作区,用于存放文件
版本库与暂存区
工作区下有一个隐藏目录.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会告知那些文件被删除,这时有两种选择:
- 确实要从版本库中删除,可执行
git rm命令删除,并git commit - 手误删除文件,这时可执行
git checkout -- <filename>命令把误删的文件恢复到最新版本
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以"一键还原", 命令git rm用于删除一个文件,如果一个文件已经被提交到版本库,那永远不用担心误删,但你只能恢复文件到最新版本,你会丢失最近一次修改提交后的内容
创建SSH Key
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上新建一个仓库(或者使用已有的仓库),在本地的一个仓库中运行以下命令:
git remote add origin git@github.com:<accountname>/<localreponame>.git
添加后,远程库名字Git默认为origin,可以更改:
git push -u origin master
git push命令,实际是把当前分支master推送到远程,
如果这是你第一次推送master分支,你需要加上-u参数,Git不但会把本地的master分支内容推送到远程的新的master分支,还会把本地的master分支和远程的master分支关联起来,
在以后的推送或者拉取时可简化命令,之后只要本地作了提交,就可以通过命令:git push origin master完成提交
在第一次使用Git的clone或push命令时会得到一个SSH警告,输入yes即可
#关联一个远程库
git remote add origin git@server-name:path/repo-anme.git
克隆远程库到本地
在Github中新建库后,可以使用git clone克隆一个本地库
git clone git@github.com:<git库地址>
Git支持多种协议,包括https
windows系统:git clone <Git远程库的url>
Git分支
git branch #查看分支
git branch <name> #创建分支
git checkout <name> #切换分支
git checkout -b <name> #创建+切换分支
git merge <name> #合并某分支到当前分支
git branch -d <name> #删除分支
多个分支是共用暂存区,即如果在分支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合并就看不出曾经做过合并
git merge --no-ff -m"..." <name>
以普通方式合并分支(即禁用fast forward)因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去`
分支策略:
- 在实际开发中,我们应该按照几个基本原则进行分制管理:
- master分支应该是非常稳定的,也就是仅用来发布新版本,平时不在上面干活;
- 干活都在dev分支,即devd分支是不稳定的,到某个时候,再把dev分支合并到master分支上;
- 每个人都在dev分支上工作,每个人都有自己的分支,要保存时往dev分支上合并就可以了
Bug分支
git stash命令相当于对当前工作环境做一个快照,等以后恢复环境后继续工作
在哪个分支上修复bug,就在从哪个分区创建临时分支
修复完后再提交并删除分支
git stash list #查看是否存在stash
git stash apply #恢复stash内容,该命令执行后并不删除stash内容
git stash drop #删除stash内容
git stash pop #恢复stash内容,在恢复的同时也删除内容
修复Bug时,当手头工作没有完成时,先把工作现场git stash一下,然后再去修复Bug,修复后,再git stash pop回到工作现场
Feature分支(添加新功能)
在开发新功能时最好新建一个分支,
若要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除
多人协作
git remote查看远程库的信息
git remote -v查看远程库详细的信息(上面显示了抓取和推送的<远程库名字>的地址,如果没有推送权限,就看不到push的地址)
- 推送分支:
推送分支就是把该分支上的所有本地提交推送远程库。推送时,要指定本地分支
git push <远程库名字> <本地库名字>
git pull #把最新的提交从远程库中抓取下来
抓取后在本地合并并解决冲突后再推送
- 工作模式:
- 首先,可以试图用
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绑定在一起
git tag <name> #在git中打标签应先切换至需要打标签的分支
git tag #查看所有标签默认标签是打在最新提交的commit上的
git tag <name> <commit ID> #给对应ID的commit打上标签
标签不是按时间顺序列出,而是按字母排序的,可以用git show <tagname>查看标签信息
git tag -a <tagname> -m "..." #创建带说明的标签,-a指定标签名,-m指定说明文字
git tag -d <tagname> #删除本地标签,因为创建的标签都只储存在本地,不会自动推送至远程
git push <远程库名字> <tagname> #推送某个标签到远程
git push <远程库名字> --tags #一次性推送全部尚未推送到远程的本地标签
其中在上面第一行代码中若用参数-s替换-a则可以用PGP签名标签
已推送到远程的标签的删除:
git push <远程库名字> :refs/tags/<tagname>
在Github上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送Pull request给他人仓库来贡献代码;
Fork他人仓库之后再在自己的账号下clone仓库,这样才能推送修改
自定义Git
git config --global color.ui true #git会适当显示不同的颜色
- 忽略文件
在Git工作区的根目录下有一个.gitignore文件(没有可创建),然后把要忽略的文件名填进去,Git就会自动忽略这些文件
忽略文件的原则:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是一个文件通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库;
- 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件
之后将.gitignore也提交到Git,就完成了忽略文件设置
git check-ignore #检查.gitignore文件
git add -f <filename> #强制添加文件
我们可以对.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改为gitsudo 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教程