一.相关概念及定义:
Git是目前世界上最先进的分布式版本控制系统
集中式版本控制系统:版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,
所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器
分布式版本控制系统:分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,
这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库
版本库(仓库):repository,理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,
每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”
二.git安装:
Windows下,安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功;
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
三.创建版本库并且添加文件到版本库步骤:
1.选择一个合适的地方,创建一个空目录:
$ mkdir learngit 创建一个空目录learngit
$ cd learngit
$ pwd 用于显示当前目录
/Users/michael/learngit
2.通过git init命令把这个目录变成Git可以管理的仓库: $ git init
3.添加编写好的readme.txt文件到learngit(子)目录下(可多次使用该命令添加多个文件): $ git add readme.txt
4.用命令告诉git已经将文件提交到仓库: $ git commit -m “这里写本次提交说明”
四.git几个常用命令:
1.git status:可以让我们时刻掌握仓库当前的状态
2.git diff: 可以查看修改内容
3.git log: 命令显示从最近到最远的提交(commit)日志记录
git log --pretty=online:使记录显示得更加简洁
4.git reset:把当前版本回退到前面的版本
把当前版本回退到上一个版本:$ git reset --hard HEAD^
补充:HEAD表示当前版本,上一个版本就是HEAD,上上一个版本就是HEAD,当然往上100个版本写100个比较容易数不过来,所以写成HEAD~100
5.回到未来的某个版本:$ git reset --hard 版本号(版本号写前几位就行) 版本号即为commit id
6.git reflog:用来记录你的每一次命令,找回需要的commit id
五.工作区和暂存区概念:
1.工作区:就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区
2.版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库;
最重要的就是称为stage(也叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD
3.文件往Git版本库里添加的时候,是分两步执行:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区(index或stage);
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
4.Git跟踪并管理的是修改,而非文件
六.撤销修改:
1.当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout – file
2.当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了第1种情况,第二步按第一种情况操作
3.已经提交了不合适的修改到版本库时,想要撤销本次提交,参考 $ git reset --hard 版本号,不过前提是没有推送到远程库
七.删除文件:
已经add并且commit的test文件需要删除: $ rm test.txt
1.确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit
2.删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git checkout -- test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”
八.远程仓库:
1.从本地添加到远程库(已经在本地创建了一个Git仓库想添加到Github上):
(1)首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库;
在Repository name填入learngit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库
(2)在本地的learngit仓库下运行命令:$ git remote add origin git@github.com:zhangfan123/learngit.git zhangfan123为github账户名,origin为远程库的名字
(3)把本地库的所有内容推送到远程库上:$ git push -u origin master 此时Github页面上和本地即变得一样
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
从现在起,只要本地作了提交commit,就可以通过命令:$ git push origin master 把本地master分支的最新修改推送至GitHub
2.将远程库克隆到本地:
(1)先创建远程库:登陆GitHub,创建一个新的仓库,名字叫gitskills;
勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件
(2)用命令git clone克隆一个本地库:$ git clone git@github.com:zhangfan123/gitskills.git;
进入gitskills目录看看,已经有README.md文件了
补充:Git支持多种协议:
1.通过https:速度慢以外,还有个最大的麻烦是每次推送都必须输入口令
2.通过ssh: 速度最快
九.设置ssh方法:
(1)Windows下打开Git Bash, 创建SSH Key: $ ssh-keygen -t rsa -C "youremail@example.com";
可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,
id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
(2)登陆GitHub,打开“Account settings”,“SSH Keys”页面:然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:
点“Add Key”,你就应该看到已经添加的Key
十.分支管理:
1.master分支:每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支;
HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支;
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点;
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长
2.创建切换分支步骤:
(1)我们创建dev分支,然后切换到dev分支:
$ git checkout -b dev git checkout命令加上-b参数表示创建并切换;
(2)用git branch命令查看当前分支:
$ git branch
git branch命令会列出所有分支,当前分支前面会标一个*号
结果即为: * dev
master
(3)然后,我们就可以在dev分支上正常提交,比如对readme.txt做个修改,加上一行; 然后提交
$ git add readme.txt
$ git commit -m "branch test"
(4)dev分支的工作完成,我们就可以切换回master分支:
$ git checkout master
此时,那个提交是在dev分支上,而master分支此刻的提交点并没有变
(5)把dev分支的工作成果合并到master分支上:
$ git merge dev git merge命令用于合并指定分支到当前分支
合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的
(6)合并完成后,就可以放心地删除dev分支了:
$ git branch -d dev
(7)删除后,查看branch,就只剩下master分支了:
$ git branch
结果: * master
分支命令总结:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
创建+切换分支:git checkout -b <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
3.冲突分支解决:
当Git无法自动合并分支时,就必须首先解决冲突(比如在dev分支和master都对同一文件进行了不同的修改)。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph命令可以看到分支合并图
4.合并分支merge时,加上–no-ff参数,表示禁用Fast forward,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息,合并后的历史有分支,能看出来曾经做过合并,
而fast forward合并就看不出来曾经做过合并:
$ git merge --no-ff -m "merge with no-ff" dev -m为加说明禁用fast forword
5.修复bug:
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。
6.开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除
7.查看远程库的信息,用git remote: $ git remote
git remote -v 显示更详细的信息
推送到远程库对应的远程分支上:$ git push origin master
推送其他分支,比如dev: $ git push origin dev
8.其他人的最新提交和你试图推送的提交有冲突:
先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送;
如果git pull也失败了,那么就是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:
$ git branch --set-upstream-to=origin/dev dev
再pull: $ git pull;
能git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:
$ git commit -m "fix env conflict"
$ git push origin dev
9.多人协作的工作模式:
(1)首先,可以试图用git push origin 推送自己的修改;
(2)如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
(3)如果合并有冲突,则解决冲突,并在本地提交;
(4)没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
(5)如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/
10.命令小结:
(1)查看远程库信息,使用git remote -v;
(2)本地新建的分支如果不推送到远程,对其他人就是不可见的;
(3)从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
(4)在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
(5)建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
(6)从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
11.rebase:rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比
十一.标签管理:
1.标签:tag,版本库的一个快照,就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起
2.创建标签:
(1)切换到需要打标签的分支上:
$ git branch
$ git checkout master
(2)敲命令git tag 就可以打一个新标签:$ git tag v1.0 默认为HEAD,也可以指定一个commit id
(3)可以用命令git tag查看所有标签:$ git tag
(4)给历史提交的某个版本打标签:
$ git tag v0.9 f52c633 f52c633为对应的commit id
(5)git show 查看标签信息
(6)命令git tag -a -m "blablabla…"可以指定标签信息
3.操作标签:
(1)如果标签打错了,也可以删除 $ git tag -d v0.1
(2)如果要推送某个标签到远程,使用命令git push origin v0.1
一次性推送全部尚未推送到远程的本地标签:$ git push origin --tags
(3)如果标签已经推送到远程,要删除远程标签:
先从本地删除:$ git tag -d v0.9;
然后,从远程删除格式如下:$ git push origin :refs/tags/v0.9
十二.自定义git:
1.忽略某些文件时,需要编写.gitignore;
.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理
2.让Git显示颜色,会让命令输出看起来更醒目:
$ git config --global color.ui true
十三.搭建Git服务器:
1.搭建Git服务器非常简单,要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装:
(1)安装git: $ sudo apt-get install git
(2)创建一个git用户,用来运行git服务:$ sudo adduser git
(3)创建证书登录:收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个
(4)初始化Git仓库:先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:$ sudo git init --bare sample.git
把owner改为git:$ sudo chown -R git:git sample.git
(5)禁用shell登录:
(6)克隆远程仓库: git clone git@server:/srv/sample.git
2.要方便管理公钥,用Gitosis
3.要像SVN那样变态地控制权限,用Gitolite