版本库即repository,这个目录下的所有文件都可以被git管理,每个文件的修改删除,git都能跟踪,以便任何时候都能追踪历史,还原至某一版本。
首先需要在本机创建一个专门的文件夹用来当作repository
$ mkdir repository
$ cd repository
然后通过git init
命令将仓库变成git可以管理的仓库,成功之后就会生成一个.git
隐藏文件目录
$ git init
Initialized empty Git repository in /Users/_why/repository/.git/
并不一定是要使用空文件夹作为起始repository,完全可以用一个项目作为起始repository,这里使用空的是避免个人学习时候搞坏项目。
首先这里再明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
一个合格的项目至少要有一个readme.md
文件,内容如下:
my first git repository.
i feel fucking good.
该文件可以在我们本地repository文件夹的任何地方,除了之前说的.git
隐藏文件夹。
这个时候我们要将该文件加入到repository
$ git add readme.md
然后要使用命令提交到repository
$ git commit -m 'i wrote my first readme.md' [master (root-commit) d5f1491] wrote a readme file 1 file changed, 2 insertions(+) create mode 100644 readme.md
这里的git commit -m
中的 -m
参数是本次提交的说明
任何一次成功的commit
都必须将 需要提交的文件都 add
进repository
可以一次将多个文件加入到repository
$ git add file1.txt file2.txt file3.txt
这个时候我们对readme.md 做一些改动
my first git repository.
i feel fucking good.
i made some changes in readme.me
然后运行 git status
命令:
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: readme.md
no changes added to commit (use "git add" and/or "git commit -a")
这里git 会告诉我们我们将加入本地repository的文件 改动了哪些
如果想要具体看改动了写什么东西,可以运行 git diff
$ git diff
diff --git a/readme.md b/readme.md
index dfe9329..770654e 100644
--- a/readme.md
+++ b/readme.md
@@ -1,3 +1,3 @@
my first git repository.
i feel fucking good.
+i made some changes in readme.md
这次提交仍然需要两步 git add readme.md
和 git commit
git add readme.md
git commit -m "some changes" [master 52cece9] some changes 1 file changed, 1 insertion(+)
这个时候我们再用 git status
查看,就会告诉我们当前已是最新版本
$ git status
On branch master
nothing to commit, working directory clean
实际开发过程中,我们可能对项目工程做了若干次提交,这个时候想要看我所有提交做的改变使用 git log
命令
$ git log
Author: HeapStakk .com>
Date: Tue Aug 9 17:55:48 2016 +0800
some changes
commit db9ee49571799e483242c04621f4bbcc2061dfde
Author: HeapStakk .com>
Date: Tue Aug 9 17:39:48 2016 +0800
i wrote my first readme.md
commit af62a67628018b7119e9b63aa59ef52ce8a32663
Author: HeapStakk .com>
Date: Tue Aug 9 17:36:06 2016 +0800
add 3 files
commit 7e6912a5c4f8ef307707e5fbd90a84d2d21bcc7f
Author: _why <_why@why.local>
Date: Tue Aug 9 17:32:53 2016 +0800
按照提交日期的最新至最远排序。
如果觉得这种排列方式看的不好可以尝试加入 --pretty=oneline
参数
$ git log --pretty=oneline
52cece995a1b2c9b14f19b6b154ee6c39e1aafdd some changes
db9ee49571799e483242c04621f4bbcc2061dfde i wrote my first readme.md
af62a67628018b7119e9b63aa59ef52ce8a32663 add 3 files
7e6912a5c4f8ef307707e5fbd90a84d2d21bcc7f wrote a readme file
看到一大串 52cec...aafdd
则是版本好,这是利用SHA1计算出来的。
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交52cec...aafdd
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
现在我们会退至上一个版本
$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed
然后再使用 git log --pretty=oneline
查看
git log --pretty=oneline
db9ee49571799e483242c04621f4bbcc2061dfde i wrote my first readme.md
af62a67628018b7119e9b63aa59ef52ce8a32663 add 3 files
7e6912a5c4f8ef307707e5fbd90a84d2d21bcc7f wrote a readme file
发现确实会退到上个版本
但是我回退后就后悔了,我想回到上个版本怎么办?
如果当前命令行还没有关闭,可以使用HEAD值进行回退
我之前最新版本你HEAD值为 52cec...aafdd
我们不一定要写全
$ git reset --hard 52cec
HEAD is now at 52cece9 some changes
好的 我们再用 git log --pretty-oneline
看看吧
$ git log --pretty=oneline
52cece995a1b2c9b14f19b6b154ee6c39e1aafdd some changes
db9ee49571799e483242c04621f4bbcc2061dfde i wrote my first readme.md
af62a67628018b7119e9b63aa59ef52ce8a32663 add 3 files
7e6912a5c4f8ef307707e5fbd90a84d2d21bcc7f wrote a readme file
但是如果我们回退之后直接关掉了命令行工具,怎么办,可以使用 git relog
查看
git reflog
db9ee49 HEAD@{0}: reset: moving to HEAD^
52cece9 HEAD@{1}: reset: moving to 52cec
db9ee49 HEAD@{2}: reset: moving to HEAD^
52cece9 HEAD@{3}: commit: some changes
db9ee49 HEAD@{4}: commit: i wrote my first readme.md
af62a67 HEAD@{5}: commit: add 3 files
7e6912a HEAD@{6}: commit (amend): wrote a readme file
d5f1491 HEAD@{7}: commit (initial): wrote a readme file
这里我们按照我们的操作顺序,我们可以看到 我们最新的版本应该是 52cec...aafdd
这次我们就可以再次成功的恢复之前的操作了。
我们通常可以直接从文件目录里移除没用的文件
$ rm readme.md
这个时候使用 git status
,git 就会提示哪些文件被删除
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# deleted: readme.md
#
no changes added to commit (use "git add" and/or "git commit -a")
现在有两个选择,一个是我确实要移除,另外个是我删错了。
前者使用 git rm
删除掉,并且 git commit
$ git rm readme.md
rm 'readme.md'
$ git commit -m "remove test.txt"
[master d17efd8] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 readme.me
后者则是恢复误删除文件 git checkout
$ git checkout -- readme.md
git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的repository
文件夹就是一个工作区
版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是git的版本库。
git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD。
前面讲了我们把文件往git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建git版本库时,git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
俗话说,实践出真知。现在,我们再练习一遍,先对readme.txt
做个修改,比如加上一行内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
然后,在工作区新增一个LICENSE
文本文件(内容随便写)。
先用git status
查看一下状态:
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: readme.txt
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# LICENSE
no changes added to commit (use "git add" and/or "git commit -a")
git非常清楚地告诉我们,readme.txt
被修改了,而LICENSE
还从来没有被添加过,所以它的状态是Untracked
。
现在,使用两次命令git add
,把readme.txt
和LICENSE
都添加后,用git status
再查看一下:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# new file: LICENSE
# modified: readme.txt
#
现在,暂存区的状态就变成这样了
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的: