基础篇
git 简介
Linus 创建了 Linux,后来为了解决 Linux 开发过程中的版本控制问题,用 C 语言开发了分布式版本控制系统—— Git。2008年,GitHub 网站上线,为开源项目免费提供 Git 存储,无数开源项目开始迁移至 GitHub,Git 成为最流行的分布式版本控制系统。
集中式 vs 分布式
集中式版本控制系统,版本库是集中存放在中央服务器的,工作时需要先从中央服务器取得最新的版本,修改完成后再将其推送给中央服务器。集中式版本控制系统最大的缺点就是必须联网才能工作,网速不好时,提交文件会很慢。
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,因此工作时不需要联网。和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。
安装与配置
最早 Git 是在 Linux 上开发的,但现在,Git 可以在 Linux、Unix、Mac 和 Windows 这几大平台上正常运行了。
安装 git
在 Linux 上安装 Git
如果使用的是 Debian 或 Ubuntu Linux 系统,通过一条简单的命令就可以安装
sudo apt-get install git
在 Windows 上安装 Git
有个叫做 msysGit 的项目,可以在 https://gitforwindows.org/ 上下载 Windows 版本的 Git 工具,提供了 Git Bash,Git GUI,Gitk 工具。
配置 git
Git 设置了一些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量存在gitconfig
文件中,通过git config
命令可以修改其中的配置参数。按照环境变量的作用范围大小,分别存放在以下三个不同的地方:
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。若使用git config
时用--system
选项,读写的就是这个文件。~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。若使用git config
时用--global
选项,读写的就是这个文件。- 当前项目的 Git 目录中的配置文件(也就是工作目录中的
.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。
在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig
文件。主目录即 $HOME
变量指定的目录,一般都是 C:\Documents and Settings\$USER
。
(1)配置用户信息
配置个人的用户名称和电子邮件地址:
$ git config --global user.name "your_name"
$ git config --global user.email your_name@xxx.com
如果用了 --global
选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或邮箱,只要去掉 --global
选项重新配置即可,新的设定保存在当前项目的 .git/config
文件里。
(2)文本编辑器
设置 Git 默认使用的文本编辑器, 一般可能会是 Vi 或者 Vim。
$ git config --global core.editor emacs
(3)差异分析工具
还有一个比较常用的是,在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话:
$ git config --global merge.tool vimdiff
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。
(4)查看配置信息
要检查已有的配置信息,可以使用 git config --list 命令:
$ git config --list
core.autocrlf = true
pull.rebase = false
init.defaultbranch = master
user.name = Jack
user.email = Jack@xxx.com
color.ui = auto
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig
和 ~/.gitconfig
)。
要想查看某个特定的配置参数,只要把参数名称跟在后面即可:
$ git config user.name
Jack
创建版本库
版本库又名仓库,英文名 repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被 Git 管理起来,每个文件的修改、删除,Git 都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
-
创建一个空目录:
$ mkdir learngit $ cd learngit $ pwd /Users/your_name/learngit
-
通过
git init
命令把这个目录变成 Git 可以管理的仓库:$ git init Initialized empty Git repository in /Users/your_name/learngit/.git/
此时,版本库就建好了,当前目录下会多出一个
.git
的目录,这个目录是 Git 来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把 Git 仓库给破坏了。该目录默认是隐藏的。也不一定必须在空目录下创建Git仓库,选择一个已有目录也是可以的。
用 Git 进行版本控制时,需要了解以下几个概念:
- workspace:工作区,即要进行版本控制的目录(
.git
所在的目录) - staging area:暂存区/缓存区,
.git
目录中用来存放修改的文件 - local repository:版本库或本地仓库,
.git
目录中用来存放提交的文件 - remote repository:远程仓库,
git
服务器(如github
)上存放的版本库
跟踪修改
所有的版本控制系统,只能跟踪文本文件的改动,比如 TXT 文件,网页,所有的程序代码等等,Git 也不例外。版本控制系统可以告诉你每次的改动,比如在第 5 行加了一个单词 “Linux”,在第 8 行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从 100 KB 改成了 120 KB,但到底改了啥,版本控制系统不知道,也没法知道。
因为文本是有编码的,比如中文有常用的 GBK 编码,日文有 Shift_JIS 编码,如果没有历史遗留问题,强烈建议使用标准的 UTF-8 编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
- Microsoft 的 Word 格式是二进制格式,因此,版本控制系统是没法跟踪 Word 文件的改动的。
- Git 能跟踪任何修改,如新建文件、删除文件、修改文件都是一种“修改”,都可以被跟踪。
git add
使用git add
命令,把工作区中所做的修改保存到暂存区中,此时,文件进入被跟踪状态。
# 将单个文件添加到暂存区
$ git add <file_name>
# 将工作区中的 "所有" 修改添加到暂存区,包括文件内容修改以及新建文件
# 但是删除文件这种变化不会被添加到暂存区
$ git add .
# git add --update 的缩写
# 仅跟踪已经被 add 的文件(即 tracked file),不会跟踪工作区中新建的文件
# 当已被跟踪的文件被修改或被删除时,这些变化都会被添加到暂存区
$ git add -u
# 将工作区中的所有修改添加到暂存区,包括新建文件、删除文件、修改文件
$ git add -A
git restore
使用git restore
命令可以丢弃工作区所做的修改或取消暂存。
# 在工作区中修改了文件,但还没有加入到暂存区时,
# 使用下面的命令可以丢弃工作区中所做的修改
$ git restore <file_name>
# 在工作区中修改了文件,且已经加入到暂存区时,
# 使用下面的命令可以取消暂存, 此时工作区中所做的修改还在
$ git restore --staged <file_name>
.gitignore
.gitignore
不是 Git 命令,而在项目中的一个文件,通过设置 .gitignore
文件的内容来告诉 Git 哪些文件应该被忽略,不需要进行跟踪。.gitignore
文件中每一行表示希望被忽略的文件或目录,例如:
./build
*.png
提交修改
Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然后再粘贴一样,但比复制粘贴优雅许多!Git 希望提交记录尽可能地轻量,因此在你每次进行提交时,它并不会盲目地复制整个目录。条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。
# 语法
$ git commit -m "描述提交的内容"
# 修正最新提交的内容,后面会详细介绍
$ git commit --amend
# 将所有已跟踪文件的 "修改、删除(不包括新建文件)" 变化都提交到本地仓库,即使没有添加到暂存区