先贴几篇网上找的很不错的文章(初接触博客,对一些规矩不是很懂,如果这样引用有诸如侵权等不当行为,请指正,我将即刻改正):
博客园“懵懂的菜鸟”发布的文章:
廖雪峰老师的教程:
菜鸟教程:
这些文章有很全面的Git安装使用的教程,花一些时间将这些文章看完就能对Git有一个大致的了解,基本的使用也不成问题,但对于没接触过Linux和版本控制的人来说,有些概念还是会显得比较抽象,我以同样是初学者的角度谈谈我对Git的一些理解(肯定不如大佬们深刻,可能会出现自以为是的说法,如有问题请指正),并记录一些我觉得会用到的命令。
一、Git的基本概念
1.本地仓库与版本库
本地仓库即由用户自己选定的目录(文件夹),工作区的文件及目录和Git的版本库(.git目录)都在这个目录中。
图中最左边的工作区就是电脑上能看到的,存放代码、文档等文件的目录(文件夹),这个区域一般在初始化本地仓库的时候划定,在该区域发生的文件及文件内容变动都将被跟踪,之后可以使用Git将这些变动提交到版本库记录,或使该区域的状态变更到版本库中记录的某个版本。
工作区的变动在提交到版本库时都需要先经过一下中间的暂存区,作为新手,还没能理解暂存区的作用,感觉像是把档案放进档案库前再给个机会想想有没有写错些什么。
最后右边的版本库算是Git的核心,它把之前的提交的改动按时间顺序存放,并贴上带有提交时备注的信息,版本号,提交时间、作者等信息的标签,方便在回溯版本时想起该版本的内容。实际的版本库并不是图中那样把所有内容都储存一遍,那样太耗费空间了,图画成那样是为了方便理解,事实上使用Git用不了多少空间。
如果使用Git GUI(图形界面),很多东西会更加直观,当然,那同样需要先了解Git的工作原理,不然一样抓瞎。
2.分支
Git的使用不仅仅是为了保存历史版本的代码,更重要的是协助团队进行分布式开发,因为是几个甚至几十个人同时编写一个项目,如果都在一起改动必然杂乱无章,所以使用分支来协调。分支可以看作是并行的版本库,开发编写时互不影响,在自己分支完成编写时再把改动推送到主分支和其他分支来的改动整合最终发布。
如图,红线是master分支,该分支是初始化仓库时就自动产生的主分支,按照惯例该分支的版本都是可正式发布的。也就是说,不能直接在该分支提交开发中的版本。
蓝线是dev分支,一般在初始化仓库后便立马人工创建的分支,该分支就是承担开发工作的,所有改动在这汇总,测试无误后再合并到master分支发布。
当然,虽然dev是开发分支,但同样不能容忍所有人都在这上面开发,不然一样毫无秩序,那么每个人就需要再创建一个属于自己的分支(图中绿黄紫三线就是甲乙丙的个人分支),平时在自己的分支干活,当写好一定内容需要发布时就推送到dev分支,或是有其他人向dev分支推送了改动时把那些改动合并到自己的分支,当然,如果双方的改动有冲突,还需要协商最终以谁的为准。
上图是一个使用Git进行开发的简单例子,项目开始时甲乙丙三人以dev分支为模板创建了自己的分支,然后开始开发,甲乙负责一个模块,丙负责另一个模块。甲在自己的分支写了ab,并合并到dev分支,乙写了Bc准备合并到dev分支,但因为甲已经对dev进行了改动,所以乙得先把改动合并到自己的分支,在合并中他发现,甲和自己都写了b,不过甲的写法是b,自己的写法是B,这便产生了冲突,于是需要协商,最终两人决定使用b写法。乙合并并解决冲突后将自己的改动也合并到dev分支,dev分支将这些改动合并到master分支发布,其他分支也都从dev分支合并了改动,以保证大家都是在最新的进度下进行开发(这样可以减少下次合并产生的冲突数量)。在甲乙发布第一个版本时,丙为自己的模块写了d,在同步到最新进度时,他的分支已经有abcd了,然后他紧接着开发了e,并删除了a,至此,他觉得他的模块写好了,于是将改动合并到dev分支,同样的,dev分支将这些改动合并到master分支发布了第二个版本,同时甲乙的分支也都合并了最新改动。
另外,实际应用中还有bug分支和feature的概念,因为这里只是想简单讲清楚分支的概念,实际中的模式在开头链接的文章中写的很清楚,要系统学习还是以那些文章为主。
3.远程仓库
远程仓库是将本地仓库的内容进行异地存放并提供代码交换的场所,可以自己搭建一台服务器作为远程仓库,也可以使用GitHub、coding.net这类提供仓库托管的网站。
如图ab各自使用自己的电脑开发同一个项目,他们都在自己电脑上创建了本地仓库及master分支和dev分支,并以dev分支为模板创建了自己的分支,同时在远程仓库也创建了对应的个人分支。那么项目开始后两人需要做的是,时刻关注远程仓库的master分支和dev分支是否有新的改动,若有,则将改动拉(pull)到自己相应的分支,保证这两个分支出于最新进度,并在个人分支a、b合并(merge)dev分支的改动,这时可能需要处理冲突。当在自己的个人分支a、b提交了改动后,可以选择将这些改动推(push)到远程仓库,当然也可以不这么做,时刻推送自己的分支只是为了保证电脑坏了工作不会丢失。当完成了工作后,在本地的dev分支合并(merge)个人分支的改动,然后将dev分支的改动推(push)到远程仓库,以供服务器和他人拉取。
二、常用的Git命令
1.初始化仓库
a.从头编写一个项目
从头编写一个项目,你需要选中一个目录(文件夹)在右键菜单中打开 Git Bash ,输入以下命令将其初始化为本地仓库,然后把存放代码和文档的目录放进去(或直接将那个目录初始化为本地仓库):
git init
初始化完毕,工作的内容都放进去后,输入以下命令进行第一次提交,将这些内容存入版本库,至此,Git开始发挥作用了:
git add .git commit -m"Initial file"
尔后在GitHub、coding.net这些仓库托管网站创建一个远程仓库。远程仓库创建好后可以使用 HTTPS 协议或者 SSH 协议进行访问,使用HTTPS协议需要在每次访问时输入网站登录的用户名和密码,费事且不安全,为了一劳永逸,输入以下命令创建SSH密钥,在创建期间会有各种询问,感兴趣可以看看,不然一路回车就行:
ssh-keygen -t rsa
生成的密钥一般放在 C:\Users\Administrator\.ssh 目录中,其中 id_rsa.pub 文件就是公钥,你可以在目录中找到该文件用记事本打开,也可以直接输入以下命令打开该文件:
cat ~/.ssh/id_rsa.pub
将公钥复制下来(注意不要漏了内容,也不要多了空格),粘贴到仓库托管网站的公钥设置中,这样就可以输入以下命令关联本地和远程仓库,推送本地的master分支并将其与远程仓库的master分支关联起来了。注意!命令行中的 git@git.coding.net:JasonT98/UserDemo.git 是我的SSH协议地址,你必须将其替换为自己的:
git remote add origin git@git.coding.net:JasonT98/UserDemo.gitgit push -u origin master
至此,本地和远程的仓库都初始化成功了,你可以使用Git管理版本并和同伴共同开发了。
b.中途加入一个项目
中途加入一个项目,意味着你的同伴已经建成了一个远程仓库,这时你只需要将他们的远程仓库克隆一份到本地就行,当然,前提是你也必须生成密钥然后将公钥粘贴到仓库托管网站的公钥设置中,密钥相关的操作同上。
选中你想存放项目的文件夹在右键菜单中打开 Git Bash ,输入以下命令完成克隆。注意!命令行中的 git@git.coding.net:JasonT98/UserDemo.git 是我的SSH协议地址,你必须将其替换为自己的:
git clone git@git.coding.net:JasonT98/UserDemo.git
这样轻轻松松就把同伴的代码和文档搞到手了。
(以上涉及到仓库托管网站的操作没截图举例,自己摸索问题不大,开篇的链接文章也有很详细的截图)
2.创建个人分支
之前概念有说到,不能直接在master分支上开发,要创建dev分支和个人分支,这里以创建dev分支为例。
在 Git Bash 输入以下命令,即可以master分支为模板创建并切换到 dev 分支:
git checkout –b dev
非常简单,创建新分支都会以你当前的分支为模板。另有一下常用的分支命令:
git branch #查看分支git branch fz #创建分支'fz'git checkout fz #切换至分支'fz' git checkout –b fz #创建并切换到分支'fz' git merge fz #将分支'fz'的变动到合并到当前分支 git branch –d fz #删除分支'fz' git branch –D fz #强行删除分支'fz'
下图为查看分支的结果图,当前选中的分支会被 * 标注,并显示在标题的括号中。
3.提交改动
a.查看改动情况
完成了上述内容,就可以进行开发了,开发会产生一系列文件变动,比如一个功能模块做完,就要把相关文件的变动都提交到版本库,并推送到远程仓库,这些操作同样是在 Git Bash 输入命令,首先,输入以下命令,查看当前状态:
git status
下图为结果图:
图中蓝标1234代表4种不同情况,1是已经add进暂存区等待提交到版本库,2是在工作区被删除,3是在工作区被修改,4是新添加进工作区。为了进一步确定工作区的改动是否可以提交,可以输入以下命令比较文件改动前后的变化,该命令只能比较在工作区被修改的文件(状况3):
git diff 文件名
下图为 git_test.txt 文件的变化:
其中红色减号部分是相比上一版本被删除的行,绿色加号部分是相比上一版本新增的行。
b.处理改动
确认完毕后,将需要提交的改动通过以下命令添加至暂存区:
git add . #添加所有文件的改动git add 文件名 #添加新增或被修改的文件的改动 git rm 文件名 #添加被删除的文件的改动
将需要提交的改动添加至暂存区后,输入以下命令,即可将暂存区的所有改动作为一个版本,存至版本库,其中-m后引号内的内容为版本信息,根据改动情况自行填写:
git commit -m'版本信息'
最后,输入以下命令将改动推送至远程仓库:
git push origin 分支名
如果使用的是个人分支还需输入以下命令,切换到dev分支,将改动合并后再推送:
git checkout devgit merge 个人分支名git push origin dev
—————————————— 分割线 ——————————————
上述部分已足够应对简单的流程,以下为补充部分,如无兴趣可直接看下一小节。
如果你已经将改动提交到暂存区,即status中的状况1,但这时突然不想提交这个改动了,那么可以使用以下命令将其从暂存区撤回:
git reset #撤回所有提交git reset 文件名 #撤回单个提交
另外还有一条命令:
git checkout -- 文件名
这条命令是用于撤销工作区的改动,若改动尚未添加至暂存区,则将工作区恢复到最新版本库的状态;若添加至暂存区后又作了修改,则将工作区恢复到暂存区的状态。简言之,即将工作区恢复到上一次 git add 或 git commit 时的状态。
4.同步改动
a.拉取改动
当同伴推送了新的改动时,你就需要将这些改动从远程仓库拉取到本地,首先使用以下命令切换分支:
git checkout 分支名
需要拉取哪条分支的改动,就切换到相应的分支下,随后使用以下命令拉取改动:
git pull origin 分支名
这样,你本地的这条分支的版本库就更新了。
b.合并改动
按照习惯一般需要同伴拉取的改动都是提交到dev分支下的,所以拉取改动后也只有本地的dev分支同步了进度,还需要将这些改动也合并到个人分支,以保证自己接下来的开发是在最新进度下,避免再次提交时出现大量冲突。
同样的,使用以下命令,先切换到个人分支,再将改动合并过来:
git checkout 个人分支名git merge dev #将'dev'分支的改动合并到当前分支
c.隐藏与冲突
可能你在需要进行同步的时候还有一大堆改动没有提交,这时Git不会让你切换分支,撤回改动自然是不可能的,提交不完整的改动又不符合规范,那么,可以使用以下代码将改动隐藏,待结束同步再取回继续工作:
git stash #隐藏当前改动 git stash pop #取回隐藏的改动
在合并改动或取回改动时,可能会产生冲突,如下图,输入 git status,unmerged paths 下的文件即冲突文件:
打开冲突文件,如下图部分就是冲突行:
Git使用 <<<<<<< HEAD ======= >>>>>>> master 区分冲突行,<<<<<<< HEAD ======= 之间的是当前分支的改动内容,======= >>>>>>> master 之间的是合并的分支改动的内容。在和同伴商量好最终改动结果后,用最终结果替换 <<<<<<< HEAD >>>>>>> master 之间的内容即可。最后用 git add 和 git commit 命令将改动提交,冲突成功解决,可以放心地继续工作了。
5.版本回退
a.回退到之前的版本
首先,为了确保回退的版本是你想要的版本,你可以使用以下命令查看以前各版本的信息:
git log #显示版本信息(版本号、提交人、提交时间、提交信息) git log --pretty=oneline #显示版本信息(版本号、提交信息)
下面两图依次是上面两命令的结果:
越靠上的版本是越新的版本,确定回退的版本后,使用以下命令进行回退:
git reset --hard HEAD^^ #回退2个版本(^的数量代表向前回退几个版本)git reset --hard HEAD~10 #回退10个版本git reset --hard 版本号 #回退到版本号对应版本(上图黄色字符串即版本号,输入前几位Git就能找到,但位数不能太少,一般7位即可)
b.回退到回退之前的版本
回退到过去的版本后,再用 git log 是看不到那些被回退的版本的,那么如果后悔了想要再回到“未来”怎么办?使用以下命令可以查看每一次版本和分支的变动:
git reflog
部分结果如下图:
这时你只需找到你想回到的“未来”版本的版本号,再使用 git reset --hard 版本号 命令回退到那个版本即可。