Git的指令
创建Git仓库
-
在需要创建Git仓库的目录下打开Git Bash,使用
git init
命令来初始化一个Git仓库,在执行完git init
命令后,该目录下会生成一个名为.git的隐藏目录,这个目录中包含了资源的所有元数据。1
git init
-
也可以指定目录作为Git仓库
1
git init /path/to/your/repo
将文件纳入版本控制
追踪文件
-
在Git仓库目录中,如果有几个文件需要纳入版本控制,需要先使用
git add
命令告诉Git这些文件需要被追踪。以下命令将README文件提交到仓库中。1
git add README
-
然后使用
git status
命令查看当前Git状态,会看到README文件已被跟踪,并处于暂存状态。1
2
3
4
5
6
7git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README -
现在修改一个已经被跟踪的文件“CONTRIBUTING.md”,然后运行
git status
命令,会看到如下内容:1
2
3
4
5
6
7
8
9
10
11
12
13git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
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: CONTRIBUTING.md -
文件
CONTRIBUTING.md
出现在Changes not staged for commit
这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 要暂存这次更新,需要运行git add
命令:1
2
3
4
5
6
7
8
9git add CONTRIBUTING.md
git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: CONTRIBUTING.md -
现在两个文件都已暂存,下次提交时就会一并记录到仓库。 假设此时,你想要在
CONTRIBUTING.md
里再加条注释。 重新编辑存盘后,准备好提交。 不过且慢,再运行git status
看看:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15vim CONTRIBUTING.md
git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: CONTRIBUTING.md
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: CONTRIBUTING.md -
现在
CONTRIBUTING.md
文件同时出现在暂存区和非暂存区。实际上 Git 只暂存了运行git add
命令时的版本。如果你现在提交,CONTRIBUTING.md
的版本是你最后一次运行git add
命令时的那个版本,而不是你运行git commit
时,在工作目录中的当前版本。 所以,运行了git add
之后又作了修订的文件,需要重新运行git add
把最新版本重新暂存起来:1
2
3
4
5
6
7
8
9git add CONTRIBUTING.md
git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: CONTRIBUTING.md
状态简览
-
git status
命令的输出十分详细,但其用语有些繁琐。 Git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改。 如果你使用git status -s
命令或git status --short
命令,你将得到一种格式更为紧凑的输出。1
2
3
4
5
6git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt -
新添加的未跟踪文件前面有
??
标记,新添加到暂存区中的文件前面有A
标记,修改过的文件前面有M
标记。 输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。例如,上面的状态报告显示:README
文件在工作区已修改但尚未暂存,而lib/simplegit.rb
文件已修改且已暂存。Rakefile
文件已修改,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分。
忽略文件
-
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为
.gitignore
的文件,列出要忽略的文件的模式。 来看一个实际的.gitignore
例子:1
2
3cat .gitignore
*.[oa]
*~ -
第一行告诉 Git 忽略所有以
.o
或.a
结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。 第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。 要养成一开始就为你的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdfGitHub 有一个十分详细的针对数十种项目及语言的
.gitignore
文件列表, 你可以在 https://github.com/github/gitignore 找到它。
提交更新
-
现在暂存区已经准备就绪,可以使用
git commit
提交了。1
git commit
-
然后会启动你选择的文本编辑器来输入提交说明。编辑器会显示类似下面的文本信息:
1
2
3
4
5
6
7
8
9
10
11
12
13Please enter the commit message for your changes. Lines starting
with '#' will be ignored, and an empty message aborts the commit.
On branch master
Your branch is up-to-date with 'origin/master'.
# Changes to be committed:
new file: README
modified: CONTRIBUTING.md
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C -
可以看到,默认的提交消息包含最后一次运行
git status
的输出,放在注释行里,另外开头还有一个空行,供你输入提交说明。在Vim编辑器中,可以按下i或者Insert进入编辑模式。完成编辑后按下Esc,输入:wq
保存并退出文件,如果需要放弃修改并退出,输入:q!
。
移除文件
-
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用
git rm
命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了:1
2
3
4
5
6
7
8
9
10
11git rm PROJECTS.md
git status
On branch master
Your branch is up-to-date with 'origin/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: PROJECTS.md
no changes added to commit (use "git add" and/or "git commit -a") -
如果希望Git不再跟踪文件时,文件可以继续保留在磁盘上,使用
--cache
选项:1
git rm --cached README
重命名(移动文件)
-
如果需要在Git跟踪的文件中重命名某个文件,可以使用
git mv
:1
2
3
4
5
6
7
8git mv README.md README
git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README -
运行
git mv
相当于运行了三条命令:1
2
3mv README.md README
git rm README.md
git add README
使用远程仓库
查看远程仓库
-
如果想查看你已经配置的远程仓库服务器,可以运行
git remote
命令。 它会列出你指定的每一个远程服务器的简写。 如果你已经克隆了自己的仓库,那么至少应该能看到 origin ——这是 Git 给你克隆的仓库服务器的默认名字:1
2
3
4
5
6
7
8
9
10git clone https://github.com/schacon/ticgit
Cloning into 'ticgit'...
remote: Reusing existing pack: 1857, done.
remote: Total 1857 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1857/1857), 374.35 KiB | 268.00 KiB/s, done.
Resolving deltas: 100% (772/772), done.
Checking connectivity... done.
cd ticgit
git remote
origin -
你也可以指定选项
-v
,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。1
2
3git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push) -
如果你的远程仓库不止一个,该命令会将它们全部列出。 例如,与几个协作者合作的,拥有多个远程仓库的仓库看起来像下面这样:
1
2
3
4
5
6
7
8
9
10
11
12cd grit
git remote -v
bakkdoor https://github.com/bakkdoor/grit (fetch)
bakkdoor https://github.com/bakkdoor/grit (push)
cho45 https://github.com/cho45/grit (fetch)
cho45 https://github.com/cho45/grit (push)
defunkt https://github.com/defunkt/grit (fetch)
defunkt https://github.com/defunkt/grit (push)
koke git://github.com/koke/grit.git (fetch)
koke git://github.com/koke/grit.git (push)
origin git@github.com:mojombo/grit.git (fetch)
origin git@github.com:mojombo/grit.git (push) -
如果想要查看某一个远程仓库的更多信息,可以使用
git remote show <remote>
命令。 如果想以一个特定的缩写名运行这个命令,例如origin
,会得到像下面类似的信息:1
2
3
4
5
6
7
8
9
10
11
12git remote show origin
* remote origin
Fetch URL: https://github.com/schacon/ticgit
Push URL: https://github.com/schacon/ticgit
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
添加远程仓库
-
运行
git remote add <shortname> <url>
添加一个新的远程 Git 仓库,同时指定一个方便使用的简写:1
2
3
4
5
6
7
8git remote
origin
git remote add pb https://github.com/paulboone/ticgit
git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push) -
现在你可以在命令行中使用字符串
pb
来代替整个 URL。 例如,如果你想拉取仓库中有但本地没有的信息,可以运行git fetch pb
:1
2
3
4
5
6
7
8git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit
* [new branch] master -> pb/master
* [new branch] ticgit -> pb/ticgit
重命名与移除
-
你可以运行
git remote rename
来修改一个远程仓库的简写名。 例如,想要将pb
重命名为paul
,可以用git remote rename
这样做:1
2
3
4git remote rename pb paul
git remote
origin
paul -
值得注意的是这同样也会修改你所有远程跟踪的分支名字。 那些过去引用
pb/master
的现在会引用paul/master
。如果因为一些原因想要移除一个远程仓库,可以使用git remote remove
或git remote rm
:1
2
3git remote remove paul
git remote
origin -
一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。
查看提交历史
-
在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的工具是
git log
命令。使用“simplegit”项目作为演示,首先运行下面的命令获取项目:1
git clone https://github.com/schacon/simplegit-progit
-
获取完毕后,在该项目中运行
git log
命令,可以看到如下输出:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19git log
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
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
会按时间先后顺序列出所有的提交,最近的更新排在最上面。 正如你所看到的,这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。如果希望以补丁的形式查看每次提交所引入的差异,可以使用-p
或者--patch
,同时可以限制显示的日志条目数量,例如-2
代表只显示最近的2次提交: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
41git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
Author: Scott Chacon <schacon@gmail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the verison number
diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "simplegit"
- s.version = "0.1.0"
+ s.version = "0.1.1"
s.author = "Scott Chacon"
s.email = "schacon@gmail.com"
s.summary = "A simple gem for using Git in Ruby code."
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test code
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
end
end
-
-if $0 == __FILE__
- git = SimpleGit.new
- puts git.show
-end -
使用
--stat
可以快速浏览每次提交的简略信息: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
29git log --stat
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
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(-)
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
README | 6 ++++++
Rakefile | 23 +++++++++++++++++++++++
lib/simplegit.rb | 25 +++++++++++++++++++++++++
3 files changed, 54 insertions(+) -
使用
--pretty
选项可以选择显示样式,比如在一行内查看每次提交:1
2
3
4git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) changed the verison number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test code
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit -
或者使用
--pretty=format:
来自定义显示样式:1
2
3
4git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 15 years ago : changed the verison number
085bb3b - Scott Chacon, 15 years ago : removed unnecessary test code
a11bef0 - Scott Chacon, 15 years ago : first commit--pretty=format 常用选项
选项 说明 %H
提交的完整哈希值 %h
提交的简写哈希值 %T
树的完整哈希值 %t
树的简写哈希值 %P
父提交的完整哈希值 %p
父提交的简写哈希值 %an
作者名字 %ae
作者的电子邮件地址 %ad
作者修订日期(可以用 --date=选项 来定制格式) %ar
作者修订日期,按多久以前的方式显示 %cn
提交者的名字 %ce
提交者的电子邮件地址 %cd
提交日期 %cr
提交日期(距今多长时间) %s
提交说明 git log常用选项
选项 说明 -p
按补丁格式显示每个提交引入的差异。 --stat
显示每次提交的文件修改统计信息。 --shortstat
只显示 --stat 中最后的行数修改添加移除统计。 --name-only
仅在提交信息后显示已修改的文件清单。 --name-status
显示新增、修改、删除的文件清单。 --abbrev-commit
仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 --relative-date
使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 --graph
在日志旁以 ASCII 图形显示分支与合并历史。 --pretty
使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format(用来定义自己的格式)。 --oneline
--pretty=oneline --abbrev-commit
合用的简写。限制git log输出的选项
选项 说明 -<n>
仅显示最近的 n 条提交。 --since
,--after
仅显示指定时间之后的提交。 --until
,--before
仅显示指定时间之前的提交。 --author
仅显示作者匹配指定字符串的提交。 --committer
仅显示提交者匹配指定字符串的提交。 --grep
仅显示提交说明中包含指定字符串的提交。 -S
仅显示添加或删除内容匹配指定字符串的提交。
Git的基本操作
- 以下6条命令是Git最常使用的命令:
- git clone / git fetch
- git pull
- git checkout (git switch / git restore)
- git add
- git commit
- git push
- 其中:
- workspace:工作区
- staging area:暂存区(缓存区)
- local repository:本地仓库(版本库)
- remote repository:远程仓库
git clone
-
如果需要下载Git仓库到本地目录中,可以使用下面两种指令。第一种将Git仓库克隆到当前执行Git命令的目录下,第二种将Git仓库克隆到指定目录下。当你执行
git clone
命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。其中:- <repo>:需要克隆的Git仓库
- <directory>:本地目录
1
2git clone <repo>
git clone <repo> <directory>
git fetch
-
git fetch
用于更新本地仓库,但不会自动合并或修改本地代码,在查看远程仓库最新更新、了解其他开发者的提交或者想手动处理合并时,则使用git fetch
操作,然后使用git merge
合并分支。其中:- <alias>:远程仓库的别名,通常是origin
- <branch>:分支名称,如master
1
2git fetch <alias>
git merge <alias>/<branch>
git pull
-
git pull
与git clone
的作用类似,都是从代码仓库获取代码,不同的是,git clone
会覆盖本地仓库中的内容,git pull
则是将远程拉取的代码与本地的版本合并,本质是将git fetch
和git merge
一并完成。git pull
有三种写法,第一种是从远程仓库拉取当前所跟踪的分支,第二种则指定远程分支,第三种则指定本地分支。1
2
3git pull <远程仓库名>
git pull <远程仓库名> <远程分支名>
git pull <远程仓库名> <远程分支名>:<本地分支名> -
在指定本地分支时,远程分支不可以省略,即不可以写成如下样式:
1
git pull <远程仓库名>:<本地分支名>
git checkout (git switch + git restore)
-
git checkout
用于切换本地分支,可以从当前分支切换到另一个存在的分支。同时git checkout
还可以将文件恢复到最近一次提交的状态,即撤销对文件的修改。如果需要切换分支的同时创建分支,可以使用-b
参数1
2
3git checkout <分支名>
git checkout -b <新分支名>
git checkout <文件名> -
在2.23版本中,Git引入了两个新的指令:switch和restore,替代了部分checkout的功能。其中switch用来切换分支,restore用来恢复文件,但checkout仍然可以继续使用。在使用switch切换分支时,可以使用
-c
参数同时创建分支1
2
3git switch <分支名>
git switch -c <新分支名>
gitt restore <文件名>
git add
-
git add
命令可将该文件的修改添加到暂存区。通过运行git add
命令,你可以告诉 Git 哪些文件的修改应该包含在下一次提交(commit)中。 -
添加一个或多个文件到暂存区:
1
git add [file1] [file2] ...
添加指定目录到暂存区,包括子目录:
1
git add [dir]
添加当前目录下的所有文件到暂存区:
1
git add .
git commit
-
git commit
命令将暂存区内容添加到本地仓库中。 -
提交暂存区到本地仓库中,[message] 可以是一些备注信息:
1
git commit -m
提交暂存区的指定文件到仓库区:
1
$ git commit [file1] [file2] ... -m [message]
-a
参数设置修改文件后不需要执行 git add 命令,直接来提交1
git commit -a
git push
-
使用
git push
可以将项目推送到上游,比如想要将master
分支推送到origin
服务器时:1
git push origin master
-
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会被拒绝,需要先抓取他们的工作并将其合并进你的工作后才能推送。
为提交结点打上标签
- 像其他版本控制系统(VCS)一样,Git 可以给仓库历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点(
v1.0
、v2.0
等等)。
创建标签
-
Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。
-
轻量标签没有保存任何其他信息,只需要提供标签名字:
1
git tag v1.4-lw
-
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议使用
-a
创建附注标签,这样你可以拥有以上所有信息:1
git tag -a v1.4 -m "my version 1.4"
-
标签补打
-
假设提交历史如下:
1
2git log --pretty=oneline
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile -
假设在“updated rakefile” 提交时忘记给项目打标签,可以在之后补上标签。 要在哪一次提交上打标签,就需要在命令的末尾指定哪一次提交的校验和(或部分校验和):
1
git tag -a v1.0 9fceb02
删除标签
-
要删除掉本地仓库上的标签,可以使用命令
git tag -d <tagname>
。 例如,可以使用以下命令删除一个轻量标签:1
2git tag -d v1.4
Deleted tag 'v1.4' (was e7d5add) -
上述命令并不会从任何远程仓库中移除这个标签,需要用
git push
来更新远程仓库:-
git push <remote> :refs/tags/<tagname>
,这种操作的含义是,将冒号前面的空值推送到远程标签名,从而高效地删除它:1
2
3git push origin :refs/tags/v1.4
To /git@github.com:schacon/simplegit.git
- [deleted] v1.4 -
第二种更直观的删除远程标签的方式是:
1
git push origin --delete <tagname>
-
Git别名
-
Git可以为命令设置自定义别名,通过
git config
来为命令设置别名,例如:1
2
3git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --' -
那么如果需要输入
git commit
时,就可以通过输入git ci
替代如果需要输入
git reset HEAD -- fileA
时,可以用git unstage fileA
替代