1. Git 是什么可以吃吗?
Git 是一个分布式版本控制系统,由Linus Torvalds 创作,他也是Linux 内核的最早作者。Git 的命名很有意思,该词源自英语俚语,意思大约是「混账」,是Linus Torvalds 的自嘲:
“I’m an egotistical bastard, and I name all my projects after myself. Frist Linux, now git.“
2. 人人都爱版本控制系统
以一份需要多方共同维护的产品需求文档为例,如果没有版本控制,你很可能被管理多个文件副本的恐惧支配,”我昨天和今天存的这两份文件有什么不一样?” “把文件邮件给程序猿、设计狮,他们发来了文件的修改版,这两个修改版怎么合并在一起?”
(图片From 廖雪峰的Git教程)
最终你们决定不再使用副本,在同一份文件上工作,并手动记录下每次更新的内容。
版本 | 用户 | 说明 | 日期 |
---|---|---|---|
1 | 产品汪 | 创建PRD,描述产品“核心功能1-5” | 2016/06/12 03:04 |
2 | 设计狮 | 添加了部分功能的交互效果 | 2016/07/09 12:09 |
3 | 程序猿 | 删除“核心功能2-5” | 2016/07/09 16:51 |
4 | 产品汪 | 恢复“核心功能2-5” | 2016/07/12 01:51 |
然而,这一份独一无二的文件存储在哪里?如何保证每次只有一名同事在对它进行编辑?能否自动记录每次编辑的内容?如果一次编辑出错了,能否回滚到编辑前的版本?
Linux 的创始人Linus 也面临同样的问题,世界各地的人都在为Linux 编写代码,如何管理这些代码?
事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手 工方式合并代码!
附录:Git的诞生
3. 分布式版本控制系统:每个节点都是完整的版本库
- 集中式(SVN、CVS、VSS):版本库存放在「中央服务器」
分布式(Git):没有「中央服务器」,每个人电脑上都有完整的版本库
集中式的服务器挂了所有人都挂了,因为完整仓库只存在服务器上,分布式如果github挂了你可以重新建一个服务器,然后把任何一个人的仓库clone过去
3. 安装Git
4. 创建一个版本库init
add
commit
什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
- 4.1
mkdir
创建一个空目录(选择已有文件的目录也可以):
|
|
- 4.2
git init
把目录变成Git 可以管理的仓库:
|
|
可以看到testgit 目录下生成了隐藏文件夹.git,ls -ah
可以查看隐藏文件
- 4.3 将文件添加至仓库:
在
~/learngit
目录(或其子目录)下创建文件readme.txt, 将默认编码设置为UTF-812Git is a version control system.Git is free software.用
git add
告诉Git,将文件添加到仓库:
|
|
- 用
git commit
告诉Git,将文件提交到仓库,-m "xxx"
是对本次提交内容的说明:
|
|
commit
命令返回:更新1个文件,插入2行内容
可以一次 commit
多个文件,即多次 add
一次 commit
:
|
|
5. 哪些文件被修改过status
修改了什么diff
修改 readme.txt
中的内容:
|
|
5.1 在
~/testgit
下运行git status
查看仓库当前的状态:123456789$ git statusOn branch masterChanges 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.txtno changes added to commit (use "git add" and/or "git commit -a")5.2
git diff
比较未提交至仓库的文件与已提交至仓库的文件的不同:12345678910$ git diffdiff --git a/readme.txt b/readme.txtindex d8036c1..013b5bc 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.\ No newline at end of file
6. 选择重置到你喜欢的版本log
reset —hard
reflog
再次修改 readme.txt
并提交至Git:
|
|
|
|
6.1 使用
git log
查看readme.txt
的版本记录:123456789101112131415161718$ git logcommit c5eb5497c67f4752bb53d34db54060fa99fc44acAuthor: Breakingred <837423954@qq.com>Date: Wed Apr 19 16:38:07 2017 +0800append GPLcommit 792a5afcc0efc6af27f530184f42369cd6159894Author: Breakingred <837423954@qq.com>Date: Wed Apr 19 16:36:49 2017 +0800add distributedcommit 1e4e95e625fe4af8b35315044692cd48aa695a73Author: Breakingred <837423954@qq.com>Date: Wed Apr 19 16:33:26 2017 +0800wrote a readme file注意, 5 中的修改没有
commit
,所以版本记录中只有两次的commit
记录
加上
--pretty=oneline
获得版本号(commit id
) + 版本信息的输出:1234$ git log --pretty=onelinec5eb5497c67f4752bb53d34db54060fa99fc44ac append GPL792a5afcc0efc6af27f530184f42369cd6159894 add distributed1e4e95e625fe4af8b35315044692cd48aa695a73 wrote a readme file6.2 使用
git reset
将文件重置到需要的版本,当前版本用head
表示,上一个版本head^
,上上个版本head^^
, 再上一个版本head^3
,现在讲版本回滚到add distributed
:12$ git reset --hard HEAD^HEAD is now at 792a5af add distributed用
cat
查看readme.txt
内容:123$ cat readme.txtGit is a distributed version control system.Git is free software.再看
git log
:123456789101112$ git logcommit 792a5afcc0efc6af27f530184f42369cd6159894Author: Breakingred <837423954@qq.com>Date: Wed Apr 19 16:36:49 2017 +0800add distributedcommit 1e4e95e625fe4af8b35315044692cd48aa695a73Author: Breakingred <837423954@qq.com>Date: Wed Apr 19 16:33:26 2017 +0800wrote a readme fileappend GPL
不见了!6.3 只要窗口没有关闭,可以找到
append GPL
的版本号(版本号可不写全)并恢复:12$ git reset --hard c5eb5497c67f4752bb53d34db5406HEAD is now at c5eb549 append GPL这样就又回到
append GPL
版本了,万一窗口关闭了也不必担心没有了commit id
,reflog
会记录你的每一次命令,丢失的版本号又找回来啦:123456$ git reflogc5eb549 HEAD@{0}: reset: moving to c5eb5497c67f4752bb53d34db5406792a5af HEAD@{1}: reset: moving to HEAD^c5eb549 HEAD@{2}: commit: append GPL792a5af HEAD@{3}: commit: add distributed1e4e95e HEAD@{4}: commit (initial): wrote a readme file
7. 从工作区到暂存区的原理
来自:廖雪峰的Git教程
可见的目录如
learngit
就是工作区,工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支
master
,以及指向master
的一个指针叫HEAD
。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用
git add
把文件添加进去,实际上就是把文件修改添加到暂存区;第二步是用
git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。因为我们创建Git版本库时,Git自动为我们创建了唯一一个
master
分支,所以,现在,git commit
就是往master
分支上提交更改。你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
在工作区修改文件
readme.txt
,新建文件LICENSE
,检查状态get status
:1234567891011121314$ git statusOn branch masterChanges 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.txtUntracked files:(use "git add <file>..." to include in what will be committed)LICENSEno changes added to commit (use "git add" and/or "git commit -a")readme.txt
被修改了,而LICENSE
还从来没有被添加过,所以它的状态是Untracked
add
将工作区文件修改添加至暂存区,检查状态get status
:1234567$ git statusOn branch masterChanges to be committed:(use "git reset HEAD <file>..." to unstage)new file: LICENSEmodified: readme.txt
commit
将暂存区文件提交至当前分支,目前提交至Git自动创建的唯一分支master
,检查状态get status
:123$ git statusOn branch masternothing to commit, working tree clean