一、Git是什么?
Git是一个分布式版本控制系统,功能十分强大。而CVS和SVN都是集中式的版本控制系统。那么他们的区别是什么呢?
先说集中式版本控制,所有版本控制的数据都存储在中央服务器上,用户必须连接到这个服务器才能进行操作,如提交、更新等。操作通常依赖于网络连接,离线时无法提交或查看历史记录。版本历史仅存在于中央服务器上,用户不能直接访问整个历史。如果中央服务器出现故障,所有数据可能会丢失。
再来说说分布式版本控制,分布式版本控制系统通常也有一个中央服务器,不过这个服务器的作用仅仅用来统一大家的修改,没有它依旧能够写代码,只是这样的话项目统一需要将各自的修改推送给对方。每个用户的本地电脑上都有整个版本库的完整拷贝,用户可以在本地进行所有操作,只有在需要共享时才与其他用户同步。用户可以离线工作,提交更改、查看历史记录等,待连接时再推送到中央仓库。每个用户都拥有完整的版本历史,可以随时查看和切换到任何版本。由于每个用户都有完整的版本库,所以安全性较高。
二、Git的工作区和暂存区
首先要明白工作区和暂存区的概念,工作区就是电脑上你的仓库目录,版本库就是工作区中的隐藏目录.git
,版本库中存了许多东西,其中最重要的就是暂存区,还有Git所创建的第一个分支master
,以及指向他的一个指针HEAD
。
三、Git的安装
在Windows上安装Git,可以直接从Git官网下载安装程序,然后按默认选项安装即可。这里推荐一篇安装教程,很详细。
安装完成后,在开始菜单中找到“Git Bash”,会出现一个类似命令窗口的东西,就说明安装成功。
接下来需要一步设置,在命令行输入:
$ git config --global user.name "自己的名字"
$ git config --global user.email "email地址"
注意git config
命令的--global
参数,用了该参数,表示你这台机器上的所有Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
四、创建版本库
版本库就是项目仓库,可以理解为一个目录,该目录中的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能追踪。
首先需要找个自己觉得合适的地方,右键单击文件夹在Git Bash中输入:
$ mkdir learngit
$ cd learngit
$ pwd
$ git init
pwd
命令用于显示当前目录,git init
命令初始化该目录,将其变为Git可以管理的仓库。
五、本地仓库使用
当你新建或者修改某个文件(xxx.xx)后,需要将该文件同步到本地仓库
第一步,需要将文件添加到暂存区:
$ git add xxx.xx
该命令可反复多次使用,添加多个文件
第二步,把文件添加到本地仓库,也就是master
分支
$ git commit -m "xxx"
其中,-m
后面输入的是本次提交的说明,该命令是将暂存区中的文件一起全部提交给本地仓库
当你想查看当前目录下都有哪些文件时,可以使用ls
或dir
命令。
当你想掌握当前仓库的状态,想看看具体哪些文件被修改,哪些文件被创建了,可以输入命令:
$ git status
当你想看某个文件具体修改了哪些内容,可以输入:
$ git diff xxx.xx
当你想看你的历史提交记录,可以输入:
$ git log
该命令显示从最近到最远的提交日志,当然也可以看到简略形式
$ git log --pretty=online
在Git中用HEAD表示当前版本,也就是最新提交的时候,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,也可以写成HEAD~2
当我们要把当前版本回退到上个版本,可以输入
$ git reset --hard HEAD^
--hard
会回退到上个版本的已提交状态
--soft
会回退到上个版本的未提交状态
--mixed
会回退到上个版本已添加但未提交状态
当然也可以用commit id
来回退版本,可以输入:
$ git reset --hard commit_id
当我们想看某个文件的内容时,可以输入:
$ git cat xxx.xx
Git提供了一个命令,用来记录你的每一次命令:
$ git reflog
当你想把误添加到暂存区的文件撤回到工作区,可以输入:
$ git reset HEAD xxx.xx
用HEAD
表示最新版本
当你改乱了工作区的某个文件的内容,还添加到了暂存区,想直接丢弃工作区的修改,可以输入:
$ git checkout -- file
当你直接在文件管理器中删除文件,这时工作区和版本库就不一致了,需要在版本库中删除该文件,可以输入:
$ git rm xxx.xx
然后在输入git commit -m "remove xxx.xx"
当你在工作区误删了文件,但此时版本库里还有,想恢复文件,可以输入:
$ git checkout -- xxx.xx
该命令其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以恢复。
六、远程仓库
上述所讲全是在我们自己的电脑上进行版本库管理,但实际工作情况是,有一台中央服务器,这上面存储着我们的终极版本库,我们每个人都从这台服务器上克隆一份仓库到我们的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库拉取别人的代码。
github
和gittee
都提供Git仓库托管服务,下面以此为例去创建我们自己的远程仓库。
由于本地Git仓库和Github仓库之间的传输是通过SSH加密的,所以,需要先创建SSH Key,在Git Bash命令框中输入:
$ git ssh-keygen -t rsa -C "youremail@example.com"
然后,可以在用户目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSH Key的秘钥对,id_rsa
是私钥,不能泄漏出去,id_rsa.pub
是公钥,可以公开。
然后登录Github网站,打开settings,切换到SSH and GPG keys页面,在Key的文本框中粘贴id_rsa.pub
文件的内容。Github允许添加多个Key。
接着在Github主页右上角“New repository”,可以创建一个新的Git仓库。然后我们需要将本地仓库与远程仓库关联,可以输入:
$ git remote add origin git@github.com:Github账户名/仓库名.git
origin
是远程仓库名,这是默认叫法。
下一步,需要将本地库的所有内容推送到远程库中:
$ git push -u origin master
实际上是把当前分支master
推送到远程仓库,加-u
表示将本地master
分支和远程master
分支关联起来,在以后得推送或者拉取直接git push
和git pull
就行。
从现在起,只要本地做了提交,就可以通过输入:
$ git push origin master
就能把本地分支的最新修改推送到Github。现在才是真正的分布式版本库。
当我们想查看远程仓库的信息,可以输入:
$ git remote -v
当我们想删除远程仓库,可以输入:
$ git remote rm origin
该删除其实是解除本地和远程的绑定关系。
当我们想从远程仓库克隆一个本地仓库,可以输入:
$ git clone git@github.com:Github账户名/远程仓库名.git
如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。
当某个小伙伴要从远程仓库克隆时,需要先把SSH Key加到Github,然后用克隆命令克隆,但是该克隆默认只能克隆master分支,如果还要克隆远程的dev
分支,就必须创建远程origin
的dev
分支到本地,可以输入:
$ git checkout -b dev origin/dev
接下来设置本地dev
分支与远程origin/dev
分支建立链接,可以输入:
$ git branch --set-upstream-to=origin/dev dev
然后就可以在本地dev
分支上继续修改、提交、推送。
如果推送失败,说明你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法是用git pull origin dev
把最新的提交从远程origin/dev
拉下来,然后在本地合并解决冲突,再推送。下文会讲到。
七、分支管理
为了更方便、更安全的工作,我们可以在自己的电脑上创建多个分支进行工作,待某个功能写完后,与本地master
分支合并,最后提交到远程仓库。
当我们创建dev
分支,然后切换到dev
分支,可以输入:
$ git checkout -b dev
相当于
$ git branch dev
$ git checkout dev
当我们想查看当前分支,可以输入:
$ git branch
当我们要合并俩分支,将master
分支保持与dev
分支一样的进程,可以先切换到master
分支,然后输入:
$ git merge dev
该命令用于合并指定分支到当前分支。
合并分支时,可能遇到两个分支都有各自不同的提交,此时就会产生冲突,那么此时需要我们手动去解决冲突,就是手动去修改文件内容,然后再重新提交一次。
用git log --graph --pretty=oneline --abbrev-commit
命令可以看到分支的合并情况。
合并完后,当我们想删除dev
分支,可以输入:
$ git branch -d dev
由于Git会用到Fast forword
模式,删除分支后,会丢掉分支信息,当然我们可以强制禁用该模式,在合并时可以用git merge --no-ff -m "merge with no-ff" dev
命令,然后用git log --graph
查看分支情况历史。
新版的Git提供了新的创建和切换分支的命令:
$ git switch -c dev //创建并切换到新的分支
$ git switch master //切换到已有分支
八、标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。
如果你想在Git中打标签,首先,需要切换到打标签的分支上,然后可以输入:
$ git tag v1.0
如果你想查看所有标签,可以输入:
$ git tag
标签默认是打在最新提交的commit上的,如果你想在以前的commit上打标签,可以先找到历史提交的commit id
,可以输入:
$ git log --pretty=oneline --abbrev-commit
然后打上标签,可以输入:
$ git tag v0.9 f52c633
还可以创建带有说明的标签,用-a
指定标签名,-m
指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
如果你想看到标签的说明文字,可以输入:
$ git show v0.1
如果你想删除标签,可以输入:
$ git tag -d v0.1
如果要推送某个标签到远程,可以输入:
$ git push origin v1.0
如果你想一次性推送全部尚未推送到远程的本地标签,可以输入:
$ git push origin --tags
如果你想删除一个远程的标签,你需要先在本地删除,再然后从远程删除,可以输入:
$ git push origin :refs/tags/v0.9
九、在Gitee上创建远程仓库
Gitee也提供Git仓库,且提供私有库功能。与Github一样,需要先上传SSH公钥。即在Gitee账户的设置里,找到SSH页面,在公钥的文本框中粘贴id_rsa.pub
文件的内容。
然后创建新项目
接着在本地库上与Gitee的远程库关联:
$ git remote add origin git@gitee.com:Gitee账号名/LearnGit.git
之后,就可以正常地用git push和git pull推送了。
如果使用该命令报错,说明本地库已经关联了一个名叫origin
的远程库,此时,可以先用git remote -v
查看远程库信息,这里因为我已经关联了Github的远程仓库,所以报错。
我们可以删除已有的GitHub远程库:
git remote rm origin
再关联Gitee的远程库。
如果我们既想关联Github的远程仓库,又想关联Gitee的远程仓库,这样就有多个远程库,我们需要用不同的名称来标识不同的远程库。
先关联GitHub的远程库:
$ git remote add github git@gitee.com:Gitee账号名/LearnGit.git
再关联Gitee的远程库:
$ git remote add gitee git@gitee.com:Gitee账号名/LearnGit.git
如果要推送到GitHub,使用命令:
$ git push github master
如果要推送到Gitee,使用命令:
$ git push gitee master
# 十、遇到的问题
- 新建的远程仓库,建立关联后初次pull会报错 “fatal: refusing to merge unrelated histories”,初次push也会报错 “报错 non-fast-forward”。
解决办法:
拉取远程更改:
git pull origin master --allow-unrelated-histories
处理冲突(如果有): 如果合并过程中出现冲突,解决冲突后执行:
git add .
git commit -m "Merge remote-tracking branch 'origin/master'"
推送本地更改: 解决冲突并提交后,再执行推送:
git push origin master