本文是廖雪峰Git教程的读书笔记,主要方便查阅和回忆。
Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Ubuntu安装Git只需要一条命令
sudo apt-get install git
安装完后,进行简易配置,主要是设置用户名和电子邮件地址。
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
如果使用了--global
参数,意味着,这台电脑上的所有Git仓库都会使用这个配置。
然后我们试着直接键入git
命令,看到了各种git命令的用法,这里先来一个总括,之后会解释将主要命令。
$ git
用法:git [--version] [--help] [-C ] [-c name=value]
[--exec-path[=] ] [--html-path] [--man-path] [--info-path]
[-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=] [--work-tree=] [--namespace=]
<command> []
这些是各种场合常见的 Git 命令:
开始一个工作区(参见:git help tutorial)
clone 克隆一个仓库到一个新目录
init 创建一个空的 Git 仓库或重新初始化一个已存在的仓库
在当前变更上工作(参见:git help everyday)
add 添加文件内容至索引
mv 移动或重命名一个文件、目录或符号链接
reset 重置当前 HEAD 到指定状态
rm 从工作区和索引中删除文件
检查历史和状态(参见:git help revisions)
bisect 通过二分查找定位引入 bug 的提交
grep 输出和模式匹配的行
log 显示提交日志
show 显示各种类型的对象
status 显示工作区状态
扩展、标记和调校您的历史记录
branch 列出、创建或删除分支
checkout 切换分支或恢复工作区文件
commit 记录变更到仓库
diff 显示提交之间、提交和工作区之间等的差异
merge 合并两个或更多开发历史
rebase 本地提交转移至更新后的上游分支中
tag 创建、列出、删除或校验一个 GPG 签名的标签对象
协同(参见:git help workflows)
fetch 从另外一个仓库下载对象和引用
pull 获取并整合另外的仓库或一个本地分支
push 更新远程引用和相关的对象
这里先介绍从本地创建版本库,即英文repository,可以简单理解成一个目录,这个目录里面的所有文件(不包括.git隐藏目录)都可以被Git管理起来,每个文件的修改和删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
1.创建一个空目录,一般会选择放在在home目录
$ mkdir learngit
$ cd learngit
2.使用git init
命令将这个目录变成Git可以管理的仓库
$ git init
初始化空的 Git 仓库于 /home/mx/learngit/.git/
注意,.git
为隐藏目录,是Git来跟踪管理版本库的,不要去修改这个目录里面的文件,否则改乱了,就把Git仓库给破坏了。
3.为版本库添加一些文件,首先创建文件,比如:
$ cd learngit/ # 文件必须在仓库目录中
$ touch readme.md
$ gedit readme.md
# 添加两行内容:
Git is a version control system.
Git is free software.
4.使用命令git add
告诉Git,把文件添加到缓存区:
$ git add readme.txt
5.使用命令git commit
告诉Git,把文件从缓存区添加到仓库:
$ git commit -m "write a readme file"
[master (根提交) 635f829] write a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.md
这里的-m
参数是提交日志,非常需要加上,否则会有warning。git commit
命令执行成功后会告诉你,1个文件被改动(我们新添加的readme.txt文件),插入了两行内容(readme.txt有两行内容)。
为什么Git添加文件需要add
,commit
两步呢?因为commit
可以一次提交很多文件,所以你可以多次add
不同的文件,比如:
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
后面还会说到,这样的两步动作,算是一种“后悔药”机制,可以方便撤销修改。
Git仓库有三个区域:工作区、暂存区和版本库
git add
指向的区域。git commit
指向的区域。1.我们修改readme.md文件:
# 原文件
Git is a version control system.
Git is free software.
# 修改第一行内容
Git is a distributed version control system.
Git is free software.
2.运行git status
命令看看结果:
$ git status # 返回仓库当前状态
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: readme.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
Git看出来我修改过了redme.md文件,但是还没提交。
3.运行git diff
这个命令查看刚才到底修改了什么内容:
$ git diff readme.md
diff --git a/readme.md b/readme.md
index 46d49bf..a14450e 100644
--- a/readme.md
+++ b/readme.md
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
修改结果一目了然,先删了第1行,然后添加了第1行。
4.运行git add
和git commit
提交修改后的文件:
$ git add readme.md
$ git commit -m "change readme.md"
[master 50cbd9a] change readme.md
1 file changed, 1 insertion(+), 1 deletion(-)
这里注意,任何本地文件的修改,如果没有使用git add
添加到缓存区,git commit
是不会提交修改的。多次修改,应遵循这样的路径:第一次修改 -> git add
-> 第二次修改 -> git add
-> git commit
。
5.如果有很多修改需要添加到缓存区,比如从什么地方复制了大量文件,那可以使用git add .
进行一次性添加当前所有修改。
每次我们使用git commit
提交文件,会生成一个快照 ,我们在Github上看到的commits就是人家的提交记录(快照)。
1.运行git log
查看版本变更:
$ git log
commit 50cbd9a7c82ce35920472a5debfe4256ea7b2001
Author: jmx5200 .com>
Date: Thu Aug 31 20:34:06 2017 +0800
change readme.md
commit 635f829e5ce22aa97dc2cbdf2b6ae792d6c46699
Author: jmx5200 .com>
Date: Thu Aug 31 20:15:33 2017 +0800
write a readme file
命令显示,我这里从近到远,提交了2次,存在2个版本。而50cbd9a7c82ce35920472a5debfe4256ea7b2001
这串数字代表的就是commit id
(版本号)。
2.回退到上个版本,也就是退到“write a readme file”那个版本去。运行git reset
命令,还要加上版本参数--hard
(hard参数不仅仅是将本地版本库的头指针全部重置到指定版本,也会重置暂存区,并且会将工作区代码也回退到这个版本 ) 。在Git中,用HEAD
(文件指针)表示当前版本,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,往上倒推n个版本可以写为HEAD~n
。
$ git reset --hard HEAD^
HEAD 现在位于 635f829 write a readme file
$ cat readme.md
Git is a version control system.
Git is free software.
果然,回退到了前一个版本。此时再运行git log
查看版本变更,发现版本日志就剩一条了。
$ git log
commit 635f829e5ce22aa97dc2cbdf2b6ae792d6c46699
Author: jmx5200
Date: Thu Aug 31 20:15:33 2017 +0800
write a readme file
3.回到原来的新版本。如果此时发现回退错了,想反悔怎么办?Git提供了两种办法。
1)如果回退之前使用过git log
查看过日志,可以在终端把版本号找出来,比如我现在找到”change readme.md”这一版的版本号是”50cbd9a7c82ce35920472a5debfe4256ea7b2001”,就可用这个版本号充当--hard
的参数值(随便敲5,6位,Git能自己搜索匹配):
$ git reset --hard 50cbd9
HEAD 现在位于 50cbd9a change readme.md
$ cat readme.md
Git is a distributed version control system.
Git is free software.
又变回来了,真是神奇!
2)运行git reflog
命令查看每一次Git操作命令,从中找出新版本的版本号:
$ git reflog
635f829 HEAD@{0}: reset: moving to HEAD^
50cbd9a HEAD@{1}: reset: moving to 50cbd9
635f829 HEAD@{2}: reset: moving to HEAD^
50cbd9a HEAD@{3}: commit: change readme.md
635f829 HEAD@{4}: commit (initial): write a readme file
现在找到新版本的版本号前面是“50cbd9a…”,也可以回到原来的新版本。
我们试着在readme.md文件中添加一行,然后保存。
# 原文件
Git is a distributed version control system.
Git is free software.
# 添加一行
$ echo "I love Git" >> readme.md
$ cat readme.md
Git is a distributed version control system.
Git is free software.
I love Git
$ git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: readme.md
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
现在发现画蛇添足,想要撤销修改,应该怎么办呢,这里有3种情况。
1)如果仅仅修改了readme.md,没有运行git add
,则运行git checkout -- file
可还原。
$ git checkout -- readme.md
$ cat readme.md
Git is a distributed version control system.
Git is free software.
2)如果修改了readme.md,运行git add
添加修改到缓存区,但是没有运行git commit
提交,可以用git reset HEAD file
回到场景1,然后再撤销。
$ git reset HEAD readme.md
重置后取消暂存的变更:
M readme.md
$ git checkout -- readme.md
$ cat readme.md
Git is a distributed version control system.
Git is free software.
3)如果修改了readme.md,运行git add
添加修改到缓存区,也运行了git commit
提交(但是没有推送远程),可以运行git reset HEAD^ readme.txt
,把readme.md的commit提交撤销,回到场景2,然后再依次处理。
这里能这么操作是因为:git reset
命令既可以回退版本,也可以把暂存区的修改回退到工作区。
首先创建一个新文件test.txt,往里头写点东西,然后提交到本地仓库:
$ touch test.txt
$ echo "test how to delete" >> test.txt
$ cat test.txt
test how to delete
$ git add test.txt
$ git commit -m "add test.txt"
[master 52df0ee] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
现在本地仓库里面已经有test.txt文件了,如果觉得没啥用,想删除这个文件,一般而言,会直接使用rm
命令:
$ rm test.txt
$ git status
位于分支 master
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
修改: readme.md
尚未暂存以备提交的变更:
(使用 "git add/rm <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
删除: test.txt
Git知道我们删除了本地的文件,如果真心想从版本库中删除文件,那么还要多运行一次git rm
, 然后再git commit
。
$ git rm test.txt
rm 'test.txt'
$ git commit -m "delete test.txt"
[master c646c8e] delete test.txt
2 files changed, 2 deletions(-)
delete mode 100644 test.txt
这样,版本库和本地文件就保持一致了。但是如果删错(仅删除了本地文件,没有commit提交),那也可以从版本库中恢复过来。
$ git checkout -- test.txt
$ ls
readme.md test.txt