参考教程:https://download.csdn.net/download/essity/10359744
1 集中式vs分布式
集中式:集中式版本控制系统,版本库是集中存放在中央服务器的,⽽干活的时候,⽤的都是⾃⼰的电脑,所以要先从中央服务器取得最新的版本,然后开始干 活,干完活了,再把⾃⼰的活推送给中央服务器。中央服务器就好⽐是⼀个图书馆,你要改⼀本书,必须先从图书馆借出来,然后回到家⾃⼰改,改完了,再放回图书馆。
分布式:分布式版本控制系统根本没有“中央服务器”,每个⼈的电脑上都是⼀个完整的版本库,这 样,你⼯作的时候,就不需要联⺴了,因为版本库就在你⾃⼰的电脑上。既然每个⼈电脑上都有⼀个完整的版本库,那多个⼈如何协作呢?⽐⽅说你在⾃⼰电脑上改 了⽂件A,你的同事也在他的电脑上改了⽂件A,这时,你们俩之间只需把各⾃的修改推送给对⽅,就可以互相看到对⽅的修改了。
2 git全局配置
git安装完成后,还需要最后⼀步设置,在命令⾏输⼊:
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
因为Git是分布式版本控制系统,所以,每个机器都必须⾃报家⻔:你的名字和Email地址。注意git config命令的–global参数,⽤了这个参数,表⽰你这台机器上所有的Git仓库都会使⽤这个配置,当然也可以对某个仓库指定不同的⽤户名和Email地址。
3 创建版本库
版本库⼜名仓库,英⽂名repository,可以简单理解成⼀个目录,这个目录⾥⾯的所有⽂件都可以被Git管理起来,每个⽂件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
$ mkdir learngit
$ cd learngit
$ pwd
/Users/michael/learngit
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
瞬间Git就把仓库建好了,⽽且告诉你是⼀个空的仓库(empty Git repository),可以发现当前目录下多了⼀个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要⼿动修改这个目录⾥⾯的⽂件,不然改乱了,就把Git仓库给破坏了。也不⼀定必须在空目录下创建Git仓库,选择⼀个已经有东⻄的目录也是可以的。不建议使⽤⾃⼰正在开发的公司项目来学习Git。
4 把文件添加到版本库
所有的版本控制系统,其实只能跟踪⽂本⽂件的改动,⽐如TXT⽂件,网⻚,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,⽐如在第5⾏加了⼀个单词“Linux”。图⽚、视频这些⼆进制⽂件,虽然也能由版本控制系统管理,但没法跟踪⽂件的变化,只能把⼆进制⽂件每次改动串起来,也就是只知道图⽚从100KB改成了120KB,但到底改了啥,版本控制系统不知道。Microsoft的Word格式是⼆进制格式。因为⽂本是有编码的,⽐如中⽂有常⽤的GBK编码,⽇⽂有Shift_JIS编码,如果没有历史遗留问题,强烈建议使⽤标准的UTF-8编码,所有语⾔使⽤同⼀种编码,既没有冲突,⼜被所有平台所⽀持。
把⼀个⽂件放到Git仓库只需要两步。
第⼀步,⽤命令git add告诉Git,把⽂件添加到仓库:
$ git add readme.txt
第二步,用命令git commit告诉Git,把文件提交到仓库:
$ git commit -m "wrote a readme file"
[master (root-commit) cb926e7] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
简单解释⼀下git commit命令, -m后⾯输⼊的是本次提交的说明,可以输⼊任意内容,当然最好是有意义的,这样你就能从历史记录⾥⽅便地找到改动记录。
5 工作区、暂存区和版本库
工作区(Working Directory):指的是在PC中能看得到的创建的一个管理仓库的目录,即当前项目目录。
版本库(Repository):工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
把文件往Git版本库里添加的时候,第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
github的作用其实就是一个远程磁盘,保存代码,方便管理。
6 版本控制
一、git status(当前转态)
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working
directory)
#
# modified: readme.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
git status命令可以让我们时刻掌握仓库当前的状态,上⾯的命令告诉我们,readme.txt被修改过了,但还没有准备提交的修改。
二、git diff(修改内容)
虽然Git告诉我们readme.txt被修改了,但如果能看看具体修改了什么内容,⾃然是很好的。所以,需要⽤git diff这个命令看看:
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
知道了对readme.txt作了什么修改后,再把它提交到仓库就放⼼多了,提交修改和提交新⽂件是⼀样的两步,第⼀步是git add,第⼆步git commit;
三、git log(提交历史)
当你觉得⽂件修改到⼀定程度的时候,就可以“保存⼀个快照”,这个快照在Git中被称为commit。⼀旦你把⽂件改乱了,或者误 删了⽂件,还可以从最近的⼀个commit恢复,然后继续⼯作,⽽不是把⼏个月的⼯作成果全部丢失。
git log命令显⽰从最近到最远的提交⽇志。如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数。
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
⼀⼤串类似“ 3628164…882e1e0”的是commit id(版本号),和SVN不⼀样,Git的commit id不是1,2,3……递增的数字,⽽是⼀个SHA1计算出来的⼀个⾮常⼤的数字,⽤⼗六进制表⽰。为什么commit id需要⽤这么⼀⼤串数字表⽰呢?因为Git是分布式的版本控制系统,后⾯我们还要研究多⼈在同⼀个版本库⾥⼯作,如果⼤家都⽤1,2,3……作为版本号,那肯定就冲突了。
四、git reset(版本回退)
在Git中,⽤HEAD表⽰当前版本,也就是最新的提交,上⼀个版本就是HEAD^,上上⼀个版本就是HEAD^^,当然往上100 个版本写100个^⽐较容易数不过来,所以写成HEAD~100。
现在,我们要把当前版本“append GPL”回退到上⼀个版本“add distributed”,就可
以使⽤git reset命令:
$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed
目前使用git log的时候:
$ git log
commit ea34578d5496d7dd233c827ed32a8cd576c5ee85
Author: Michael Liao <[email protected]>
Date: Tue Aug 20 14:53:12 2013 +0800
add distributed
commit cb926e7ea50ad11b8f9e909c05226233bf755030
Author: Michael Liao <[email protected]>
Date: Mon Aug 19 17:51:55 2013 +0800
wrote a readme file
如果要回去,只要上⾯的命令⾏窗⼝还没有被关掉,你就可以顺着往上找啊找啊,找到那个“append GPL”的commit id是“3628164…”,于是就可以指定回到未来的某个版本:
$ git reset --hard 3628164
HEAD is now at 3628164 append GPL
版本号没必要写全,前⼏位就可以了,Git会⾃动去找。当然也不能只写前⼀两位,因为Git可能会找到多个版本号,就⽆法确定是哪⼀个了。
Git的版本回退速度⾮常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向“append GPL”。
五、git reflog(命令历史)
如果关掉了电脑,第⼆天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?
当你⽤$ git reset --hard HEAD^回退到“add distributed”版本时,再想恢复到“append GPL”,就必须找到“append GPL”的commit id。Git提供了⼀个命令git reflog⽤来记录你的每⼀次命令:
$ git reflog
ea34578 [email protected]{0}: reset: moving to HEAD^
3628164 [email protected]{1}: commit: append GPL
ea34578 [email protected]{2}: commit: add distributed
cb926e7 [email protected]{3}: commit (initial): wrote a readme file
终于舒了⼝⽓,第⼆⾏显⽰“append GPL”的commit id是3628164,现在,你⼜可以乘坐时光机回到未来了。
六、git diff HEAD(文件不同)
修改提交后,⽤git diff HEAD -- filename命令可以查看⼯作区和版本库⾥⾯最新版本的区别。
七、撤销修改
命令git checkout -- readme.txt意思就是,把readme.txt⽂件在⼯作区的修改全部撤销,这⾥有两种情况:
⼀种是readme.txt⾃修改后还没有被放到暂存区,现在,撤销修改就回到和版本库⼀模⼀样的状态;
⼀种是readme.txt已经添加到暂存区后,⼜作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个⽂件回到最近⼀次git commit或git add时的状态。
如果git add了,在commit之前,想要撤销修改,⽤命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回⼯作区。
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
八、删除文件
7 文件管理
8 远程仓库
(github的使用不做介绍)由于本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要⼀点设置:
第1步:创建SSH Key。在⽤户主⺫录下,看看有没有.ssh⺫录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个⽂件,如果已经有了,可直接跳到下⼀步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:
$ ssh-****** -t rsa -C "[email protected]"
你需要把邮件地址换成你⾃⼰的邮件地址,然后⼀路回⻋,使⽤默认值即可,由于这个Key也不是⽤于军事目的,所以也⽆需设置密码。如果⼀切顺利的话,可以在⽤户主目录⾥找到.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。为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,⽽不是别⼈冒充的,⽽Git⽀持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你⾃⼰才能推送。当然,GitHub允许你添加多个Key。假定你有若干电脑,你⼀会⼉在公司提交,⼀会⼉在家⾥提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
第3步:登陆验证,使用命令:
$ ssh -T [email protected]
如果初次设置的话,会出现如下界面,输入yes 同意即可:
第4步:添加远程库,现在的情景是,你已经在本地创建了⼀个Git仓库后,又想在GitHub创建⼀个Git仓库,并且让这两个仓库进⾏远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他⼈通过该仓库来协作,真是⼀举多得。先在github创建一个空仓库,在本地的同名仓库下:
$ git remote add origin [email protected]:michaelliao/learngit.git
michaelliao替换成你⾃⼰的GitHub账户名,添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字⼀看就知道是远程库。
第5步:就可以把本地库的所有内容推送到远程库上:
$ git push -u origin master
Counting objects: 19, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (19/19), done.
Writing objects: 100% (19/19), 13.73 KiB, done.
Total 23 (delta 6), reused 0 (delta 0)
To [email protected]:michaelliao/learngit.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
把本地库的内容推送到远程,⽤git push命令,实际上是把当前分支master推送到远程。由于远程库是空的,我们第⼀次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。推送成功后,可以⽴刻在GitHub⻚⾯中看到远程库的内容已经和本地⼀模⼀样。
第6步:从现在起,只要本地作了提交,就可以通过命令:
$ git push origin master
9 github概述
git支持https和git两种传输协议,github分享链接时会有两种协议可选:
git使用https协议,每次pull, push都会提示要输入密码,使用git协议,然后使用ssh**,这样免去每次都输密码的麻烦
10 遇到的问题
一、使用ssh连接远程主机时:
大概意思就是说**权限的文件不能为777,不能被其他用户读取。了解了问题后,修改**文件权限为700就OK了。
二、fatal: remote origin already exists.
$ git remote rm origin