说明
本篇文章是本人回顾git知识点时从《progit》一书中摘抄出来的笔记,毕竟好记性不如烂笔头嘛,不然我也不会回顾了……
另请大神绕路,不喜勿喷……
本篇文章先走马观花般地看看git的使用,具体的每条命令的详解请看后续文章
本篇文章篇幅比较长,是本人回顾git知识点时从《progit》一书中摘抄出来的笔记,毕竟好记性不如烂笔头嘛,不然我也不会回顾了……
另请大神绕路,不喜勿喷……
1 获取git仓库
1.1 建立空仓库
1.2 将已有目录纳入git仓库
1 2
| $ cd some_dir $ git init
|
1.3 clone现有本地仓库
1
| $ git clone <location> [new-name]
|
1 2 3 4 5 6 7 8 9
| $ git init repo-1 Initialized empty Git repository in G:/tmp/git-tmp/repo-1/.git/ # 克隆仓库repo-1 并重命名为repo-1-clone # 也可以不指定别名 但此处若不指定别名会有两个相同名字的仓库而报错 $ git clone repo-1/ repo-1-clone Cloning into 'repo-1-clone'... warning: You appear to have cloned an empty repository. done.
|
1.4 clone现有远程仓库
1
| git clone <remote-url> [new-name]
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| # clone远程仓库不指定新仓库名 $ git clone https://github.com/java-template/jt-808-protocol.git Cloning into 'jt-808-protocol'... remote: Counting objects: 57, done. remote: Compressing objects: 100% (47/47), done. remote: Total 57 (delta 5), reused 50 (delta 2), pack-reused 0 Unpacking objects: 100% (57/57), done. # clone远程仓库并重命名为jt-808-protocol-new $ git clone https://github.com/java-template/jt-808-protocol.git jt-808-protocol-new Cloning into 'jt-808-protocol-new'... remote: Counting objects: 57, done. remote: Compressing objects: 100% (47/47), done. remote: Total 57 (delta 5), reused 50 (delta 2), pack-reused 0 Unpacking objects: 100% (57/57), done. # 两个仓库如下 $ ls jt-808-protocol/ jt-808-protocol-new/
|
2 记录变更
初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,也是未修改状态。
当你修改了文件的内容后,文件的特征码就变了,此时文件处于已修改状态。
来看看《progit》一书中对git文件状态变更的图解:
该小节的命令都是在以下的repo-2中操作的:
1 2 3 4
| $ git init git-repo-2 Initialized empty Git repository in G:/tmp/git-tmp/git-repo-2/.git/ $ cd git-repo-2/
|
2.1 git status
该命令可以用来查看文件的状态:已修改,未跟踪等。
新建的仓库,或者刚刚clone过来的仓库都是非常“干净的”。
此时使用status
命令会显示工作区是clean
的。
1 2 3 4 5 6
| $ git status On branch master Initial commit nothing to commit (create/copy files and use "git add" to track)
|
默认情况下,git status
命令的输出非常多,可以加选项-s
或--short
来简化输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| # 添加个新的空白文件index.html $ touch.exe index.html #查看状态 $ git status On branch master Initial commit Untracked files: # 未跟踪的文件列表如下 (use "git add <file>..." to include in what will be committed) index.html nothing added to commit but untracked files present (use "git add" to track) $ git status -s ?? index.html
|
git status -s 简化输出后,最前面的两个问号表示未跟踪的文件。其他的前缀情况下文。
git status 前缀说明
- ??: 新添加的未跟踪文件
- A: 新添加到暂存区中的文件
- M: 修改过的文件
- 出现在右边的 M 表示该文件被修改了但是还没放入暂存区
- 出现在靠左边的 M 表示该文件被修改了并放入了暂存区
2.2 git add
该命令将修改过的文件加入暂存区,待下次提交到历史记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ git add index.html $ git status On branch master Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: index.html $ git status -s A index.html $
|
git status -s 简化输出后,最前面的A表示新添加到暂存区中的文件。
1 2 3 4 5 6 7 8 9 10
| # 修改文件index.html $ echo "hello" >> index.html # A--在暂存区,M--修改过 $ git status -s AM index.html $ git add index.html $ git status -s A index.html $
|
2.3 git commit
该命令将暂存区中待提交的文件提交到历史记录中。
1 2
| git commit git commit -m "some notes"
|
1 2 3 4 5
| $ git commit -m "first commit" [master (root-commit) e500b7a] first commit 2 files changed, 2 insertions(+) create mode 100644 index.html create mode 100644 main.html
|
当然,也可以跳过git add
这一步,直接将修改的文件加入历史记录。使用选项-a
即可。
1 2
| git commit -a git commit -a -m "some notes"
|
2.4 git rm
如果有个已被git管理(跟踪)的文件不想被管理了。
那么应该从暂存区中移除它,而后再次提交即可。
而命令git rm
就是从暂存区移除文件的。
1 2 3 4 5 6 7 8 9 10 11 12 13
| //从暂存区移除main.html (master) $ git rm main.html rm 'main.html' // D表示已删除 (master) $ git status -s D main.html //从暂存区移除后,提交到历史记录 (master) $ git commit -m "del main.html" [master b05b2e9] del main.html 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 main.html
|
使用选项-cached
可以从历史记录中删除文件。
2.5 .gitignore
在实际工作中,往往有些文件我们是不需要提交到历史记录的。
比如:eclipse等IDE产生的工程配置文件.project,.classpath等。
此时,.gitignore
文件就派上用场了。在该文件中的内容都是git忽略的文件。
只需要在和.git
目录同级创建一个名为.gitignore
的文件即可。
在该文件中写入文件名、目录名等即可(支持通配符)。
以下是该文件中一些特殊的写法:
1 2 3 4 5 6 7
| *.[oa] # test.a test.o !abc.o # 该文件(abc.o)不被忽略 \!abc.f # 此处转义,代表文件名为"!abc.f"的文件被忽略 xyz # 文件xyz将被忽略 xyz/ # 录xyz将被忽略 **/xyz # 所有目录下名为xyz的子目录将被忽略
|
2.6 git diff
就像《progit》一书中说的,你会经常想:哪些文件以及修改了,但是没有添加到暂存区?哪些文件暂存了,但是没有提交?
此处说的git diff
可以用来干这事。它也能比较某个文件在不同版本之间的变更。
git diff
: 工作区和暂存区之间的差异
git diff --cached
: 暂存区和历史记录之间的差异
git diff --staged
: 同上
2.7 git tag
该命令可以给某个特定的历史提交打上标记,以区分于其他普通的历史提交。
此处以git的项目仓库作为示例,看看tag的基本操作:
1 2 3 4 5 6 7 8
| $ git clone https://github.com/git/git.git Cloning into 'git'... remote: Counting objects: 217337, done. remote: Total 217337 (delta 0), reused 0 (delta 0), pack-reused 217337 Receiving objects: 100% (217337/217337), 78.90 MiB | 893.00 KiB/s, done. Resolving deltas: 100% (159424/159424), done. $ cd git
|
列出标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| # 列出所有tag $ git tag gitgui-0.10.0 gitgui-0.10.1 gitgui-0.10.2 gitgui-0.11.0 …………………… v2.9.0-rc2 v2.9.1 v2.9.2 v2.9.3 # 过滤 $ git tag -l 'v2.9.*' v2.9.0 v2.9.0-rc0 v2.9.0-rc1 v2.9.0-rc2 v2.9.1 v2.9.2 v2.9.3
|
标签类型
- 轻量标签(lightweight):一个特定提交的引用
- 附注标签(annotated):存储在 Git 数据库中的一个完整对象
- 打标签者的名字、电子邮件地址、日期时间
- 还有一个标签信息
- 并且可以使用 GNU Privacy Guard(GPG)签名与验证
为当前历史记录创建普通标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # 创建普通标签 $ git tag 'my-tag-1' # 列出标签 $ git tag -l 'my*' my-tag-1 # 显示详细信息 $ git show my-tag-1 commit 80ba04ed9b07c34af9cc644f2183b3b80fd81744 Merge: 2076907 22af6fe Author: Junio C Hamano <gitster@pobox.com> Date: Mon Feb 20 22:01:59 2017 -0800 Merge branch 'svn-escape-backslash' of git://bogomips.org/git-svn * 'svn-escape-backslash' of git://bogomips.org/git-svn: git-svn: escape backslashes in refnames
|
为当前历史记录创建附注标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| # 创建附注标签 $ git tag -a 'my-tag-2' -m 'my tag 2' $ git tag -l 'my-tag*' my-tag-1 my-tag-2 # 显示内容 $ git show my-tag-2 tag my-tag-2 Tagger: hylexus <hylexus@163.com> Date: Thu Feb 23 16:41:05 2017 +0800 my tag 2 # 此处的信息为创建时指定的-m选项的内容 commit 80ba04ed9b07c34af9cc644f2183b3b80fd81744 Merge: 2076907 22af6fe Author: Junio C Hamano <gitster@pobox.com> Date: Mon Feb 20 22:01:59 2017 -0800 Merge branch 'svn-escape-backslash' of git://bogomips.org/git-svn * 'svn-escape-backslash' of git://bogomips.org/git-svn: git-svn: escape backslashes in refnames
|
为指定的历史提交创建附注标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #为指定的历史提交创建附注标签 # 显示最近两次的提交 $ git log --oneline -2 80ba04e Merge branch 'svn-escape-backslash' of git://bogomips.org/git-svn 2076907 Git 2.12-rc2 # 为倒数第二次历史提交添加附注标签 $ git tag -a 'tag-2-1' 2076907 -m 'tag test' # 查看 $ git show tag-2-1 tag tag-2-1 Tagger: hylexus <hylexus@163.com> Date: Thu Feb 23 16:59:38 2017 +0800 tag test commit 20769079d22a9f8010232bdf6131918c33a1bf69 Author: Junio C Hamano <gitster@pobox.com> Date: Fri Feb 17 14:00:19 2017 -0800 Git 2.12-rc2 Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
3 查看提交历史
所有的历史提交记录都在.git
目录中,可以使用git log
来查看历史。
默认情况下,git log
会按提交时间列出所有的更新,最近的更新排在最上面。
列出每次提交的SHA-1校验和、作者的名字和电子邮件地址、提交时间以及提交说明。
此处就以《progit》一书中的仓库来做示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $ git clone https://github.com/schacon/simplegit-progit my-pro $ cd my-pro $ git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 10:31:28 2008 -0700 first commit
|
git log 常用选项
-p
: 每次提交的内容差异
-n
: n是一个正整数,表示只显示最近n次的提交
--stat
: 显示每次提交的概述性信息
--shortstat
: 只显示--stat
中的最后的统计信息
--name-only
: 仅在提交信息后显示已修改的文件清单
--name-status
: 显示新增、修改、删除的文件清单
--abbrev-commit
: 仅显示SHA-1特征码的前几个字符,而非所有的40个字符
--relative-date
: 使用较短的相对时间显示(比如,“2 weeks ago”)
--pretty
: 使用其他格式显示历史提交信息
- oneline
- short
- full
- fuller
- format
--graph
显示 ASCII 图形表示的分支合并历史
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| # 显示最近两次提交的概述性信息 $ git log --stat -2 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code lib/simplegit.rb | 5 ----- 1 file changed, 5 deletions(-) # 最近两次提交,统计信息 $ git log --shortstat -2 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number 1 file changed, 1 insertion(+), 1 deletion(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code 1 file changed, 5 deletions(-) $ git log --graph --all --decorate --oneline * ca82a6d (HEAD -> master, origin/master, origin/HEAD) changed the verison number * 085bb3b removed unnecessary test code * a11bef0 first commit $ git log --pretty=format:"%h - %an, %ar : %s" ca82a6d - Scott Chacon, 9 years ago : changed the verison number 085bb3b - Scott Chacon, 9 years ago : removed unnecessary test code a11bef0 - Scott Chacon, 9 years ago : first commit
|
来自《progit》一书中的截图:
4 撤销操作
4.1 amend
该命令会将暂存区中的文件提交。
如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。
可以达到覆盖提交注释的目的。
4.2 git reset
1 2 3 4 5 6 7
| $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: Main.java modified: index.html
|
正如git给你提示的一样:use “git reset HEAD …” to unstage。
可以使用 git reset HEAD 来将文件取消暂存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| $ git reset HEAD Main.java index.html Unstaged changes after reset: M Main.java M index.html $ 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: Main.java modified: index.html no changes added to commit (use "git add" and/or "git commit -a")
|
4.3 checkout – file
该命令可以将文件还原成上次提交时的样子。
reset 和 git checkout – file的区别
简言之,git checkout -- file
修改工作区,而git reset
修改的是暂存区。
5 别名
和linux
的shell
命令一样,你可以给git命令起简短的别名以方便使用。
linux bash命令别名
此时ll
就和ls -a -l
一样了。
git 别名示例
1 2
| $ git config --global alias.lol 'log --decorate --graph --all --oneline' $ git config --global alias.ci commit
|
现在,就可以使用git ci
来代替git commit
了。
其实,和linux系统
一样,git所有的配置都是在配置文件里的:
1 2 3 4 5 6 7 8 9 10
| # global级别的配置文件内容如下 $ cat ~/.gitconfig [user] name = hylexus email = hylexus@163.com [alias] lol = log --decorate --graph --all --oneline ci = commit [credential] helper = manager
|
参考资料