| //查看某个命令文档 |
| git help <command> |
| git <command> -h |
| git <command> --help |
| |
| |
| mkdir /Users/linhaifeng/pro |
| |
| |
| cd /Users/linhaifeng/pro |
| git init |
| |
| |
| 1、 |
| 创建版本库,版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。 |
| |
| 2、 |
| 在仓库目录下执行git init后会生成一个隐藏目录.git,该隐藏目录就是Git用来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。 |
| |
| 3、 |
| 如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。 |
| |
| 4、 |
| 后期的git命令都需要在仓库目录下执行,在仓库目录外执行git命令是没有意义的 |
Git只能管理文本文件不能管理二进制文件
Git每一次提交版本保存的都是对文件内容的完整快照,快照作何解释呢?
所以:
| 如果我的项目大小是10M,那Git占用的空间是不是随着提交次数的增加线性增加呢?我提交(commit)了10次,占用空间是不是100M呢?很显然不是,Git是很智能的,如果文件没有变化,它只会保存一个指向上一个版本的文件的`指针`,即,对于一个特定版本的文件,Git只会保存一个副本,但可以有多个指向该文件的`指针`。 |
另外注意
| Git最适合保存文本文件,事实上Git就是被设计出来就是为了保存文本文件的,像各种语言的源代码,因为Git可以对文本文件进行很好的压缩和差异分析(大家都见识过了,Git的差异分析可以精确到你添加或者删除了某个字母)。而二进制文件像视频,图片等,Git也能管理,但不能取得较好的效果(压缩比率低,不能差异分析)。实验证明,一个 500k 的文本文件经Git压缩后仅 50k 左右,稍微改变内容后两次提交,会有两个 50k 左右的文件,没错的,保存的是完整快照。而对于二进制文件,像视频,图片,压缩率非常小, Git 占用空间几乎随着提交次数线性增长。 |
Git把管理的文本文件分为两个区域、四种状态。
-
1、工作区:即仓库目录
| |
| |
| $ cd /Users/linhaifeng/pro |
| |
| $ git status |
| |
| $ echo "hello egon" >> readme.txt |
| |
| $ git status |
-
2、版本库:即仓库目录下的.git目录,.git不属于工作区
|
|
|
|
| git add 文件1 |
| git add 文件1 文件2 |
| git add . |
| |
| |
| |
| git commit -m "第一次提交" |
| |
| |
| git config --local user.name 'egon' |
| git config --local user.email 'egon@example.com' |
| 配置级别 |
| –local(默认,高级优先):只影响本地仓库 |
| –global(中优先级):只影响所有当前用户的git仓库 |
| –system(低优先级):影响到全系统的git仓库 |
| |
| |
| git log |
| git log --pretty=oneline |
| git log --color --graph |
| 查看reflog,用于找到回滚后的日志 |
| git reflog |
目前已使用命令如下,使用下述命令已经可以代替本地多个文件保存版本的方式
| |
| mkdir /Users/linhaifeng/pro |
| cd /Users/linhaifeng/pro |
| git init |
| |
| |
| git config --local user.name 'Egon' |
| git config --local user.email 'egon@example.com' |
| |
| |
| git status |
| |
| |
| git add 文件名 |
| |
| |
| git commit -m '提交信息' |
| |
| |
| git log |
| git log --pretty=oneline |
| |
| git reflog |
我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,目前为止,我们执行的git commit
就是往master
分支上提交更改。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
,HEAD
指针指向的就是当前在用的版本
Git的版本回退速度非常快,因为当你回退版本的时候,Git仅仅是把HEAD指向了一个指定的版本,然后顺便把工作区的文件更新了。
从当前版本,回到过去的版本,按图所示是向左回退
当前版本为版本3,回退到版本1,命令如下
| |
| $ git log --pretty=oneline |
| 87e199e0a766ecb10028ab93fe57fb4b326445fa (HEAD -> master) 版本3 |
| 353b5afb8784f0e19c8dab83be1cb97a93b13bd4 版本2 |
| b740905aaf2753572a714ccdf3bd58a1d437148a 版本1 |
| |
| |
| |
| $ git reset --hard HEAD^ |
| HEAD is now at 353b5af 版本2 |
| |
| |
| $ git reset --hard 353b5afb8784f0e19c8dab83be1cb97a93b13bd4 |
从当前版本,回到未来的版本,按图所示是向右前进
当前版本为版本1,前进到版本3,命令如下
| |
| $ git log --pretty=oneline |
| 353b5afb8784f0e19c8dab83be1cb97a93b13bd4 (HEAD -> master) 版本2 |
| b740905aaf2753572a714ccdf3bd58a1d437148a 版本1 |
| |
| |
| $ git reflog |
| ...... |
| 87e199e HEAD@{6}: commit: 版本3 |
| 353b5af HEAD@{7}: commit: 版本2 |
| b740905 (HEAD -> master) HEAD@{8}: commit (initial): 版本1 |
| |
| |
| $ git reset --hard 87e199e |
| HEAD is now at 87e199e 版本3 |
总结:
- 1、
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。
- 2、穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。
- 3、要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
场景1:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考上一小节版本回退,不过前提是没有推送到远程库。
场景2:
前提:如果当前文件的内容已经被提交到版本库
操作:之后又修改了该文件,并且git add添加到了暂存区,后续又修改了文件
撤销:
先执行
git reset HEAD `将文件从暂存区拿回工作区
再执行
git checkout — `将工作区的修改还原到原来的状态(即上一次git commit的状态)
场景3:
前提:如果当前文件的内容从未被提交到版本库
操作:修改了该文件,并且git add添加到了暂存区,后续又修改了文件
撤销:
此时无法执行
git reset HEAD `
应该执行
git checkout — `将工作区的修改还原到git add时文件的内容
总之,git checkout — 就是让这个文件回到最近一次
git commit或
git add`时的状态。
注意,
git checkout -- file
命令中的--
很重要,没有--
,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout
命令。
Git比其他版本控制系统优秀的一个重要原因就是:Git跟踪并管理的是修改,而非文件。每次修改都需要先add到暂存区,才能提交到版本库,如果每次修改后,不用add添加到暂存区,就不会被commit提交到版本库
| $ echo "hello" > a.txt |
| $ git add a.txt |
| $ echo "world" >> a.txt |
| $ git commit -m "版本1" |
| |
| $ git status |
| $ git diff HEAD -- a.txt |
| diff --git a/a.txt b/a.txt |
| index ce01362..94954ab 100644 |
| --- a/a.txt |
| +++ b/a.txt |
| @@ -1 +1,2 @@ |
| hello |
| +world |
上述情况,我们可以在版本1的基础上继续操作:将第二次修改也add到暂存区,然后再commit一个“版本2”到版本库,也可以在当初的时候先别着急将第一次的修改commit提交成”版本1“,先将第二次修改的内容也add到暂存区,然后与第一次的修改合并到一起提交成一个版本
在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt
到Git并且提交:
| $ git add test.txt |
| |
| $ git commit -m "v1" |
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm
命令删了:
这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status
命令会立刻告诉你哪些文件被删除了:
| $ git status |
| On branch master |
| Changes not staged for commit: |
| (use "git add/rm <file>..." to update what will be committed) |
| (use "git checkout -- <file>..." to discard changes in working directory) |
| |
| deleted: test.txt |
| |
| no changes added to commit (use "git add" and/or "git commit -a") |
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且git commit
:
| $ git rm -f test.txt |
| rm 'test.txt' |
| |
| $ git commit -m "remove test.txt" |
| [master d46f35e] remove test.txt |
| 1 file changed, 1 deletion(-) |
| delete mode 100644 test.txt |
现在,文件就从版本库中被删除了。
补充:
| 可以配置.gitignore配置忽略文件,这些文件不被git追踪 |
| |
| git rm --cached :仅从暂存区删除 |
| git rm :从暂存区与工作目录同时删除 |
| git rm $(git ls-files --deleted):删除所有被跟踪,但是在工作目录被删除的文件 |
小提示:先手动删除文件,然后使用git rm 和git add效果是一样的,都会从版本库中删除掉文件。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
| $ git checkout -- test.txt |
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!
命令git rm
用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。