分布式版本控制系统Git学习笔记

Git 是目前世界上最先进的分布式版本控制系统。

安装

Windows 下直接官网下,Linux 下可以直接 sudo apt-get install git

使用下面的命令来设置本地的账户名字与邮箱地址。

1
2
git config --global user.name "Your Name"
git config --global user.email "email@example.com"

Windows 下出现「Git Credential Manager for Windows」对话框,关闭需要git config --edit --system,然后删除helper = manager行。但据说根据环境及安装时行为不同,有不同关闭方案

每次远程操作都要输密码很烦?某次输入后git config --global credential.helper store即可。

创建版本库

版本库,就是仓库,英文即为 repository 。

选择一个根目录。

如果你使用 Windows 系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。(啊,当然这提醒说不定已经过时了)

第二步,通过git init命令把这个目录变成 Git 可以管理的仓库。

然后根目录下就会多出一个.git的隐藏目录,如果你没有看到.git目录,用ls -ah命令就可以看见。

把文件添加到版本库

首先这里再明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如 TXT 文件,网页,所有的程序代码等等,Git 也不例外。版本控制系统可以告诉你每次的改动,比如在第 5 行加了一个单词 “Linux” ,在第 8 行删了一个单词 “Windows” 。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从 100KB 改成了 120KB ,但到底改了啥,版本控制系统不知道,也没法知道。
不幸的是, Microsoft 的 Word 格式是二进制格式,因此,版本控制系统是没法跟踪 Word 文件的改动的,前面我们举的例子只是为了演示,如果要真正使用版本控制系统,就要以纯文本方式编写文件。
因为文本是有编码的,比如中文有常用的 GBK 编码,日文有 Shift_JIS 编码,如果没有历史遗留问题,强烈建议使用标准的 UTF-8 编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。

使用 Windows 要特别注意:
千万不要使用 Windows 自带的记事本编辑任何文本文件。原因是 Microsoft 开发记事本的团队使用了一个非常弱智的行为来保存 UTF-8 编码的文件,他们自作聪明地在每个文件开头添加了 0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个 “?” ,明明正确的程序一编译就报语法错误,等等。这些都是由记事本的弱智行为带来的。

言归正传,把一个文件添加到 Git 仓库需要两步。

  1. 把文件添加或更新到仓库:
1
2
git add <file>
git add <file1> <file2> ...

执行上面的命令,没有任何显示,这就对了,Unix 的哲学是“没有消息就是好消息”,说明添加或修改成功。

  1. 把文件提交(commit)到仓库:
1
git commit -m "massage"

-m 后面输入的字符串是对本次提交的说明,可以输入任意内容,当然最好是有意义的。

掌握工作区状态

git status命令可以让我们时刻掌握工作区当前的状态。

就比如说原博客给的一个例子:

1
2
3
4
5
6
7
8
9
$ 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")

上面的命令输出告诉我们,readme.txt被修改过了,但还没有准备提交的修改。

那假如我想要知道readme.txt哪里被修改了怎么办?这时就需要使用git diff命令来查看。

例如原博客给的一个例子:

1
2
3
4
5
6
7
8
9
$ 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.

git diff顾名思义就是查看 difference ,显示的格式正是 Unix 通用的 diff 格式。可以从上面的命令输出看到,我们在第一行添加了一个 distributed 单词。

也可以git diff <file>来查看单个文件的修改。

查看历史提交记录

git log指令可以显示从最近到最远的提交日志。

会显示每次提交的 commit id, Author, Date 与我们在提交时写的<message>

如果嫌输出信息太多,看得眼花缭乱的,可以使用git log --pretty=oneline,这样只会显示 commit id 和<message>

使用git reflog可以显示每一次命令,包括提交、回退版本等。

版本回退

首先, Git 必须知道当前版本是哪个版本,在 Git 中,用 HEAD 表示当前版本,也就是最新的提交,上一个版本就是 HEAD^ ,上上一个版本就是 HEAD^^ ,当然往上 100 个版本写 100 个 ^ 比较容易数不过来,所以写成 HEAD~100

就比如说git reset --hard "HEAD^"就回退到上一个版本。

所以说回退版本的命令就是:

1
git reset --hard <commit_id>

这样就回退到你需要的版本了。

但是如果要恢复新版本怎么办?

通过git reflog查看新版本对应的 commit id ,也使用上述指令即可。

Git 的版本回退速度非常快,因为 Git 在内部有个指向当前版本的HEAD指针,当你回退版本的时候, Git 仅仅是把HEAD修改,然后顺便把工作区的文件更新。所以不仅可以回到历史版本也可以返回新版本。

工作区与暂存区的概念

工作区

即直接能看到的目录。

版本库

打开显示隐藏目录,会发现.git目录。这个不算工作区,而是 Git 的版本库。

Git 的版本库中存了很多东西,比如称为 stage 或 index 的暂存区,及每个分支,指针HEAD

回忆我们怎么把文件往 Git 版本库里添加:

  1. git add,把文件加入暂存区。
  2. git commit,提交更改,即把把暂存区的所有内容提交到当前分支。

所以你在git status后看到的三类文件大概就是:

  1. Untracked files,从来未被添加过的文件。
  2. Changes not staged for commit,在工作区修改了但没有将修改加入暂存区的文件。
  3. Changes to be commited,加入了暂存区,还没有提交到分支的文件。

当我们加入某个文件到暂存区,之后再将其修改,未重新加入缓存区后提交到分支,则分支中的版本为先前暂存区中的版本。

可以使用git diff HEAD -- <file>验证。

参考文献

Pro Git

廖雪峰的Git教程