最近在学习廖雪峰的Git教程【链接】,记录下学习过程以便日后查阅。
ps:实际上一个月前已经把该教程撸了一遍了,但是项目中都没用到,忘的差不多了哈哈,今天有空赶紧来复习一下,让我们正式开始吧。
一、创建版本库
初始化一个Git仓库,使用
git init
命令。添加文件到Git仓库,分两步:
第一步,使用命令
git add <file>
,注意,可反复多次使用,添加多个文件;第二步,使用命令
git commit
,完成。
1、创建一个版本库非常简单。我们先创建一个名为learngit的空目录:
为了避免出现不必要的麻烦,请确保目录名(包括父目录)不包含中文
1 $ mkdir learngit //创建learngit文件夹
2 $ cd learngit //进入该文件夹
2、通过 git init
命令把这个目录变成Git可以管理的仓库:
1 $ git init
3、现在我们编写一个readme.txt
文件并放到learngit目录下,内容如下:
1 Git is a version control system.
2 Git is free software.
用命令 git add
告诉Git,把文件添加到仓库:
1 $ git add readme.txt //执行该命令,没有任何显示,这就对了
用命令 git commit
告诉Git,把文件提交到仓库:
1 $ git commit -m "wrote a readme file"
2 [master (root-commit) cb926e7] wrote a readme file
3 1 file changed, 2 insertions(+)
4 create mode 100644 readme.txt
-m
后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
你可以添加多个文件之后再提交:
1 $ git add file1.txt
2 $ git add file2.txt file3.txt
3 $ git commit -m "add 3 files."
二、时光机穿梭
- 要随时掌握工作区的状态,使用
git status
命令。- 如果
git status
告诉你有文件被修改过,用git diff
可以查看修改内容。
我们继续修改readme.txt文件,改成如下内容:
1 Git is a distributed version control system.
2 Git is free software.
git status
命令可以让我们时刻掌握仓库当前的状态
运行 git status
命令看看结果:
1 $ git status
git diff
顾名思义就是查看difference
用 git diff
这个命令看看前后区别:
1 $ git diff readme.txt
最后再用 git add -> git commit -m "xxx" 提交,"xxx"内容为备注信息
(1)版本回退
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
git log 查看历史版本记录
假定我们现在readme.txt修改之后提交了2次,那么现在就有三个版本,可用 git log 来查看历史版本记录
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上 --pretty=oneline
参数:
1 1 $ git log --pretty=oneline
2 2 3628164fb26d48395383f8f31179f24e0882e1e0 append GPL //3628164...882e1e0的是commit id(版本号)
3 3 ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
4 4 cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
git reset --hard commit_id 可以回退到上一个版本
commit_id的值可以为:HEAD^(代表上一个版本)、HEAD^^(上上个版本)、HEAD~100(前第100个版本),
也可以为代表版本号的数字。版本号没必要写全,前几位就可以了,Git会自动去找。
1 $ git reset --hard 3628164
2 HEAD is now at 3628164 append GPL
git reflog
用来记录你的每一次命令
你可以用 git reflog 命令来查看命令记录,方便将版本还原成最新版本
1 $ git reflog 2 ea34578 HEAD@{0}: reset: moving to HEAD^ 3 3628164 HEAD@{1}: commit: append GPL 4 ea34578 HEAD@{2}: commit: add distributed 5 cb926e7 HEAD@{3}: commit (initial): wrote a readme file
(2)工作区与暂存区
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用 git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用 git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在 git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后一次性提交暂存区的所有修改
(3)管理修改
将readme.txt修改一次并用 git add 命令将其添加到暂存区之后,再次修改readme.txt,然后用 git commit -m "xxx" 将其提交,你会发现只有第一次的修改被提交了。
这是因为在工作区的第二次修改并没有放入暂存区,所以,git commit
只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
正确的流程:第一次修改 -> git add
-> 第二次修改 -> git add
-> git commit
(4)撤销修改
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- file
。场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步:
第一步用命令
git reset HEAD file
,就回到了场景1。第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考 版本回退 一节,不过前提是没有推送到远程库。
命令 git checkout -- readme.txt
意思就是,把 readme.txt
文件在工作区的修改全部撤销,这里有两种情况:
一种是 readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是 readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次 git commit
或 git add
时的状态。
(5)删除文件
当你将工作区的一个文件 git add 提交到暂存区并且 git commit -m "xxx" 到版本库之后,将工作区的文件删除。这时工作区和版本库就不同了,你有两种选择:
1、你也想将版本库的该文件删除,那就用命令 git rm
删掉,并且 git commit
:
1 $ git rm test.txt 2 rm 'test.txt' 3 $ git commit -m "remove test.txt" 4 [master d17efd8] remove test.txt 5 1 file changed, 1 deletion(-) 6 delete mode 100644 test.txt
2、刚刚的删除是误删,我想恢复工作区的该文件:
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
1 $ git checkout -- test.txt
三、远程仓库
(1)添加远程库
要关联一个远程库,使用命令
git remote add origin git@github.com:cutPicturesMan/learngit2.git
关联后,使用命令
git push -u origin master
第一次推送master分支的所有内容;此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master
推送最新修改;修改关联的远程仓库:
方法一:git remote set-url origin URL
方法二:1、先删除 git remote rm origin
2、再添加新的地址 git remote add origin git@github.com:cutPicturesMan/learngit3.git
(2)从远程库克隆
首先,登陆GitHub,创建一个新的仓库,下一步是用命令 git clone
克隆一个本地库
1 $ git clone git@github.com:cutPicturesMan/clone.git
2 Cloning into 'gitskills'... 3 remote: Counting objects: 3, done. 4 remote: Total 3 (delta 0), reused 0 (delta 0) 5 Receiving objects: 100% (3/3), done. 6 7 $ cd gitskills 8 $ ls 9 README.md
Git支持多种协议,包括https
,但通过ssh
支持的原生git
协议速度最快。
四、分支管理
(1)创建与合并分支
查看分支:
git branch
创建分支:
git branch <name>
切换分支:
git checkout <name>
创建+切换分支:
git checkout -b <name>
合并某分支到当前分支:
git merge <name>
删除分支:
git branch -d <name>
一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点:
当我们创建新的分支,例如dev
时,Git新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上:
Git创建一个分支很快,因为除了增加一个dev
指针,改改HEAD
的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变
假如我们在dev
上的工作完成了,就可以把dev
合并到master
上。Git怎么合并呢?最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支:
(2)解决冲突
在master主分支上新建一个分支feature,修改text.txt内容并 git add text.txt -> git commit -m "feature" 后 git checkout master 返回master主分支
在master主分支上修改text.txt内容并 git add text.txt -> git commit -m "master" 到主分支
现在,master
分支和feature1
分支各自都分别有新的提交,变成了这样:
这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突
1 $ git merge feature1 //无法合并
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
必须手动解决冲突后再提交。
修改text.txt内容并 git add text.txt -> git commit -m "conflict fixed" 后,master
分支和feature1
分支变成了下图所示:
用带参数的 git log
也可以看到分支的合并情况:
1 $ git log --graph --pretty=oneline --abbrev-commit 2 * 59bc1cb conflict fixed 3 | 4 | * 75a857c AND simple 5 * | 400b400 & simple 6 |/ 7 * fec145a branch test
最后 git branch -d feature 删除分支,工作完成。