[ 摘自:廖雪峰的官方网站Git教程 ]
该系列文章摘录于廖雪峰的官方网站《Git教程》,用于记录学习的知识点及便于日后查询和复习,如有侵权请联系我进行删除或修改。
Linus反对使用集中式的版本软件CVS和SVN,后面采用商业版本控制软件BitKeeper,BitMover公司授权Linux社区免费使用该软件。但是由于Linux社区的Andrew试图破解BitKeeper的协议,被发现后BitMover公司收回免费使用权。故Linux之父Linus花了两周用C语言写出Git。
集中式的版本库是存在中央服务器的,使用时需要从服务器取得最新的版本,修改之后再上传到服务器。最大的缺点是必须联网才能工作,若在局域网内还好,如果在互联网上,遇到网速慢的情况,就非常棘手。
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!
通过如下命令查看系统是否安装Git:
$ git
Debian或Ubuntu,通过如下命令进行安装:
$ sudo apt-get install git
若使用老版本的Debian或Ubuntu,要把命令改为:
$ sudo apt-get install git-core
因为以前有个软件也叫GIT(GNU Interactive Tools),结果Git就只能叫git-core了。由于Git名气实在太大,后来就把GNU Interactive Tools改成gnuit,git-core正式改为git。
如果是其他Linux版本,可以直接通过源码安装。先从Git官网下载源码,然后解压,依次输入:
$ ./config
$ make
$ sudo make install
在Windows上使用Git,可以从Git官网直接下载安装程序,然后按默认选项安装即可。
安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。
注意:git config命令的--global
参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
版本库又名仓库,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
首先这里再明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但是只能知道改了,不知道改了啥。不幸的是,Microsoft的Word格式是二进制格式。
初始化Git仓库:
$ git init
git init
命令把当前目录变成git可以管理的仓库,执行完该命令之后可以发现当前目录下多了一个.git
的目录,这个目录是Git来跟踪管理版本库的,不要手动去修改这个目录里面的文件。
有一点需要注意的是,如果使用windows系统,为了避免各种莫名其妙的问题,请确保git仓库的目录名称(包括父目录)不包含中文。
因为文本是有编码的,比如中文有常用的GBK编码,日文有Shift_JIS编码,如果没有历史遗留问题,强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
使用Windows的童鞋要特别注意:
千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等,都是由记事本的弱智行为带来的。建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可。
分两步:
第一步,用git add
命令把文件添加到仓库,格式如下:
$ git add
注意:可反复多次使用,添加多个文件,也可以一次添加多个文件。
第二步,用git commit
命令把文件提交到仓库,格式如下:
$ git commit -m
-m
后面输入的
是本次提交的说明,即更新记录。
git commmit
可以一次提交很多文件,把git add
到仓库的文件都提交到仓库。
查看工作区的状态(仓库文件的修改和提交状态等):
$ git status
查看文件的修改内容:
$ git diff
查看历史日志:
$ git log
日志中显示的如 1094adb… 的是commit id(版本号)。
查看简洁版日志:
$ git log --pretty=oneline
简洁版日志只会显示版本号和提交日志。
版本回退:
$ git reset --hard
这个版本号就是通过git log
查看到的,版本号不需要写全,只需要写前面的一部分即可,可以到版本号指定的版本,可以是历史版本也可以是未来的版本(未来的版本意思是你先回到了历史版本,然后需要再回到回退前的版本)。
HEAD表示当前版本,上一个版本就是HEAD^
,上上个版本就是HEAD^^
,以此类推…但是不可能往上100个版本就用100个^,故表示为HEAD~100。如:
$ git reset --hard HEAD^
回退到上一个版本。
查看历史命令:
$ git reflog
可以通过这个命令查看回退前的版本号,之后就可以通过git reset --hard
到未来的版本。
工作区就是我们通过git init
初始化的文件夹。
版本库是指工作区下的.git
文件夹。
暂存区的就是git add
后存放修改内容的地方,通过git commit
将暂存区的内容进行提交。
git commit
只是把暂存区的修改提交了,工作区的修改并不会提交,也就是说只会提交git add
的文件,对于修改后没有git add
的文件不会提交。
查看工作区和版本库里面最新版本的区别:
$ git diff HEAD --
丢弃工作区的修改,不丢弃已经到暂存区的修改内容:
$ git checkout --
适用场景:当你修改了工作区的内容,想直接丢弃工作区的修改时。
撤销暂存区的修改,重新放回工作区:
$ git reset HEAD
之后你可以再次通过git checkout --
丢弃工作区的修改。
适用场景:当你将修改添加到暂存区时,想丢弃暂存区的修改时。
已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库(也就是没有git push
到远程仓库)。
从版本库中删除文件:
$ git rm
$ git commit -m
从版本库中恢复文件(用版本库中的版本替换工作区中的版本):
$ git checkout --
远程仓库有两种:
我们目前只介绍GitHub仓库,由于本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以需要如下设置:
创建SSH Key
在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。
如果没有(当然有了也可以重新生成),打开Git Bash,创建SSH Key:
$ ssh-keygen -t rsa -C "[email protected]"
你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可。
如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
配置Github
登陆GitHub,打开“Settings”,“SSH and GPG Keys”页面,然后点击“New SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容。
SSH Key是为了让GitHub识别出你推送的提交确实是你推送的,而不是别人冒充的。所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
a. 添加远程库步骤如下:
b. 将已有的本地仓库与GitHub仓库关联
$ git remote add origin 远程仓库地址
如:
$ git remote add origin git@github.com:hess-hxf/Accumulation-fund-calculation.git
添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是不建议这么做。
c. 将本地仓库的内容推送到远程库
$ git push -u origin master //会让你输入GitHub的账户名和密码,验证成功才能推送到远程库
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。只要本地作了提交,就可以通过命令:$ git push origin master
把本地master分支的最新修改推送至GitHub。
要克隆一个仓库,首先必须知道仓库的地址(GitHub给出的地址不止一个,包括ssh和https两种协议地址),然后使用git clone <仓库地址>
命令克隆。
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
没有分支的风险:
假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活。如果等代码全部写完再一次性提交,又存在丢失每天进度的巨大风险。
分支在实际中的作用:
有了分支,这些问题就迎刃而解,你创建属于自己的分支,别人看不到,你在你自己的分支上工作,可以随意提交,不影响原来的分支,开发完毕之后,再一次性合并到原来的分支上,这样既安全,又不影响别人工作。
Git鼓励大量使用分支。
查看当前分支:
$ git branch
git branch
命令会列出所有分支,当前分支前面会标出*
号。
创建分支:
$ git branch
切换分支:
$ git checkout
或
$ git switch //切换分支这个动作,用switch更科学
创建+切换分支:
$ git checkout -b
或
$ git switch -c
合并某分支到当前分支:
$ git merge
删除分支:
$ git branch -d
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容(通过vi进入冲突文件时可以看到Git用<<<<<<<,=======,>>>>>>>
标记出不同分支的内容),再提交。
查看冲突的文件:
$ git status
查看分支合并图:
$ git log --graph
或
$ git log --graph --pretty=oneline --abbrev-commit //常用
在实际开发中,我们应该按照几个基本原则进行分支管理:
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。加上--no-ff
参数就可以用普通模式合并,Git就会在merge时生成一个新的commit,合并后的历史有分支信息,能看出来曾经做过合并。
如将dev分支合并到master上:
$ git merge --no-ff -m "merge with no-ff" dev
因为使用--no-ff
合并会创建一个新的commit,所以加上-m
参数,把commit描述写上去。
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash
一下,也就是把当前工作现场保存起来,然后去修复bug,修复后,再恢复现场,有两种恢复方式:
$ git stash apply
$ git stash drop
这种方式恢复后,stash内容并不删除,你需要用git stash drop
来删除;
$ git stash pop
git stash pop
,恢复的同时把stash内容也删了。你可以多次stash,恢复的时候,先用git stash list
查看,然后恢复指定的stash,通过如下命令:
$ git stash apply stash@{0}
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick
命令,把bug提交的修改“复制”到当前分支,避免重复劳动。当然也可以在dev分支上修改bug,再“复制”到master分支。
开发一个新功能,最好新建一个分支,在上面开发,完成后合并,最后删除feature分支;
删除分支(已经被合并的分支):
$ git branch -d
如果要丢弃一个没有被合并过的分支:
$ git branch -D
未被合并过的分支使用git branch -d
无法删除,需要使用-D
选项强行删除。
查看远程库的信息:
$ git remote
显示更详细的信息:
$ git remote -v
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如dev,就改成:
$ git push origin dev
但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!
在本地创建和远程分支对应的分支:
$ git checkout -b branch-name origin/branch-name
从远程抓取分支:
$ git pull
$ git push origin -name>
$ git pull
git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,使用如下命令:$ git branch --set-upstream-to -name> origin/-name>
$ git push origin -name>
发布一个版本时,通常先在版本库中打一个标签(tag),标签虽然是版本库的快照,但其实它就是指向某个commit的指针。
tag其实就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。
创建标签:
$ git tag
commit_id
是可选的,如果没有该项则默认对最新提交的commit打标签,若指定commit_id
则代表对指定的commit打标签。 $ git tag -a -m msg
-a
指定标签名,-m
指定说明文字。查看所有标签:
$ git tag
查看指定标签信息:
$ git show
注意: 标签总是和某个commit挂钩,如果这个commit既出现在master分支,又出现了在dev分支,那么在这两个分支上都可以看到这个标签。
推送本地指定标签:
$ git push origin
推送本地所有标签:
$ git push origin --tags
删除本地标签(还未推送到远程):
$ git tag -d
删除远程标签(确认是否删除远程库的标签,可以登录Github查看):
先从本地删除:
$ git tag -d
再删除远程标签:
$ git push origin :refs/tags/
假设我们参与开源项目bootstrap,官方仓库twbs/bootstrap
,Github上克隆的仓库my/bootstrap
,及本地仓库的关系如下图:
码云是国内的Git托管服务,相比于Github访问速度更快。
具体使用参见:
https://www.liaoxuefeng.com/wiki/896043488029600/1163625339727712
配置Git显示颜色:
$ git config --global color.ui true
忽略文件的原则:
.class
文件如何忽略文件:
.gitignore
文件.gitignore
文件内可以填写注释,用#
.gitignore
到Git上有时候,提交文件到Git,发现提交不了,可能是因为被.gitignore
文件忽略了,强制提交使用-f
选项:
$ git add -f
并且可以用git check-ignore
命令检查是哪个规则导致:
$ git check-ignore -v
配置别名命令如下:
$ git config --global alias.别名 现有命令
--global
是针对当前用户起作用的,如果不加,那只对当前仓库起作用。
Git的配置文件:
每个仓库的配置都放在.git/config
文件中,别名就在[alias]
后面,要删除别名,直接把对应的行删掉即可。
当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中。
配置别名除了通过命令,还可以直接修改配置文件。
Ubuntu系统搭建Git服务器:
$ sudo apt-get install git
$ sudo adduser git
id_rsa.pub
文件,把所有公钥导入到/home/git/.ssh/authorized_keys
文件里,一行一个。/srv/sample.git
,在/srv
目录下输入命令:$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git
结尾,然后把所有者改为git:$ sudo chown -R git:git sample.git
git:x:1001:1001:,,,:/home/git:/bin/bash
改为
git:x:1001:1001:,,,:/home/git:/usr/git-shell
$ git clone git@server:/srv/sample.git
团队较大,无法通过收集公钥放到服务器这种手段来实现,要方便管理公钥,可以使用Gitosis软件。
要像SVN那样变态的控制权限,用Gitolite软件。
Source Tree是由Atlassian开发的免费Git图形界面工具,可以操作任何Git库。
具体操作参见:
https://www.liaoxuefeng.com/wiki/896043488029600/1317161920364578