0
点赞
收藏
分享

微信扫一扫

【Git】基础及常用命令

云上笔记 2022-05-01 阅读 84
git

1. 获取 Git 仓库

通常有两种获取 Git 项目仓库的方式:

  1. 将尚未进行版本控制的本地目录转换为 Git 仓库;
  2. 从其它服务器 克隆 一个已存在的 Git 仓库。

两种方式都会在本地机器上得到一个工作就绪的 Git 仓库。

1.1 在已存在目录中初始化仓库

如果你有一个尚未进行版本控制的项目目录,想要用 Git 来控制它,那么首先需要进入该项目目录中。 不同系统上的做法不同:
在 Linux 上:

$ cd /home/user/my_project

在 macOS 上:

$ cd /Users/user/my_project

在 Windows 上:

$ cd /c/user/my_project

之后执行:

$ git init

该命令将创建一个名为 .git 的子目录,这个子目录含有初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 但在此时,仅仅是做了一个初始化的操作,项目里的文件还没有被跟踪。 可以通过 git add 命令来指定所需的文件来进行追踪,然后执行 git commit

$ git add .
$ git commit -m 'initial project version'

1.2 克隆现有的仓库

使用git clone <url>命令获得一份已经存在了的 Git 仓库的拷贝,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。比如,要克隆 Git 的链接库 libgit2,并自定义本地仓库的名字为“mylibgit”,可以用下面的命令:

$ git clone https://github.com/libgit2/libgit2 mylibgit

2. 记录每次更新到仓库

2.1 记录每次更新到仓库

工作目录下的每一个文件只有以下两种状态:

  • 已跟踪: 被纳入了版本控制的文件( Git 已经知道的文件),在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区。
  • 未跟踪: 除已跟踪文件外的所有文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有被放入暂存区。

编辑过某些文件之后,,Git 将它们标记为已修改文件。 可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改。下图描述了文件的状态变化周期:
文件的状态变化周期

2.2 检查当前文件状态

可以用 git status 命令查看哪些文件处于什么状态。 在克隆仓库mylibgit后,没有修改任何文件,使用此命令,会看到类似这样的输出:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

在项目下创建一个新的 README 文件,使用 git status 命令,可以看到一个新的未跟踪文件 README 出现在 Untracked files 下面,且字体为红色:

$ echo 'mylibgit' > README
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        README

nothing added to commit but untracked files present (use "git add" to track)

2.3 跟踪新文件

使用命令 git add 开始跟踪一个文件:

$ git add README

此时再运行 git status 命令,会看到 README 文件已被跟踪(绿色字体),并处于暂存状态:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed: # 只要在 Changes to be committed 这行下面的,就说明是已暂存状态
  (use "git restore --staged <file>..." to unstage)
        new file:   README

2.4 暂存已修改的文件

在README文件添加一行,然后运行 git status 命令,会看到下面内容:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   README

#  Changes not staged for commit 这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README

文件 README 同时出现在暂存区(绿色字体)和非暂存区(红色字体)。Git 只暂存了运行 git add 命令时的版本, 如果现在提交,README的版本是最后一次运行 git add 命令时的那个版本,而不是运行 git commit 时,在工作目录中的当前版本。所以,运行了 git add 之后又作了修订的文件,需要重新运行 git add 把最新版本重新暂存起来,然后再看看 git status 的输出:

$ git add README
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   README

2.5 状态简览

git status 命令的输出十分详细,但其用语有些繁琐。 Git 有一个选项-s(或--short)可以缩短状态命令的输出,以简洁的方式查看更改:新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记。

$ git status -s
A  README

2.6 忽略文件

有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。在这种情况下,可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。 文件 .gitignore 的格式规范如下:

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
  • 匹配模式可以以(/)开头防止递归。
  • 匹配模式可以以(/)结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式:

  • (*) 匹配零个或多个任意字符;
  • [abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
  • 问号(?)只匹配一个任意字符;
  • 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。
  • 使用两个星号(**)表示匹配任意中间目录,比如 a/**/z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等。
# 忽略所有的 .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/**/*.pdf

2.7 查看已暂存和未暂存的修改

git status 命令的输出过于简略,可以用 git diff 命令显示具体修改了什么地方,git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。
在 README 文件末尾添加一行,先不暂存, 运行 status 命令将会看到:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README

要查看尚未暂存的文件更新了哪些部分,不加参数直接输入 git diff

$ git diff
warning: LF will be replaced by CRLF in README.
The file will have its original line endings in your working directory
diff --git a/README b/README
index 41fd9ffc7..d9b17b358 100644
--- a/README
+++ b/README
@@ -1,2 +1,3 @@
 mylibgit
 hello
+world

此命令比较的是工作目录中当前文件和暂存区域快照之间的差异。也就是修改之后还没有暂存起来的变化内容。
若要查看已暂存的将要添加到下次提交里的内容,可以用 git diff --stagedgit diff --cached命令。这条命令将比对已暂存文件与最后一次提交的文件差异:

$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 000000000..41fd9ffc7
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+mylibgit
+hello

2.8 提交更新

使用git commit命令将暂存区的文件提交。 提交前,需要确认还有什么已修改或新建的文件还没有 git add 过,否则提交的时候不会记录这些尚未暂存的变化。所以,每次准备提交前,先用 git status 看下,所需要的文件是不是都已暂存起来了, 然后再运行提交命令 git commit。

$ git commit -m "readme"
[main 82e74ac39] readme
 1 file changed, 3 insertions(+)
 create mode 100644 README

提交后会显示,当前在main分支提交,本次提交的完整 SHA-1 校验和是 82e74ac39,在本次提交中,有1个文件修订过,3行添加。

2.9 跳过使用暂存区域

尽管使用暂存区域的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:

git commit -a -m 'no add'

2.10 移除文件

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件。

# 从暂存区域移除 README
$ git rm -rf README
rm 'README'

$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    README
# 提交
$ git commit -m "rm readme"
[main c5de4544a] rm readme
 1 file changed, 3 deletions(-)
 delete mode 100644 README

$ git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

2.11 移动文件

要在 Git 中对文件改名,可以这么做:

$ git mv file_from file_to

上述 git mv 相当于运行了下面三条命令:

$ mv README.md README
$ git rm README.md
$ git add README

3 查看提交历史

3.1 git log 简介

使用一个非常简单的 simplegit 项目作为示例。运行下面的命令获取该项目:

$ git clone https://github.com/schacon/simplegit-progit

在此项目中运行 git log 命令,可以看到下面的输出:

$ git 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 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。

3.2 git log 常用选项

  1. -p--patch
    它会显示每次提交所引入的差异(按补丁的格式输出)。可以限制显示的日志条目数量(不仅仅是-p选项),例如使用 -1 选项来只显示最近的一次提交:
$ git log -p -1
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."
  1. --stat
    显示每次提交的简略统计信息,使用 -1 选项来只显示最近的一次提交:
$ git log --stat -1
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(-)
  1. --pretty
    这个选项可以使用不同于默认格式的方式展示提交历史。 这个选项有一些内建的子选项。 比如 oneline 会将每个提交放在一行显示,在浏览大量的提交时非常有用;format 可以定制记录的显示格式。
$ git log --pretty=oneline -1
ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) changed the verison number

$ git log --pretty=format:"%h - %an, %ar : %s" -1
ca82a6d - Scott Chacon, 14 years ago : changed the verison number
  1. --since--until
# 列出最近两周的所有提交
$ git log --since=2.weeks
commit 759b615e6e1192742976cae2c16589811aa0d814 (HEAD -> master)
Author: zhangsan <12345@qq.com>
Date:   Sat Apr 30 17:58:38 2022 +0800

    initial project version

# 列出2022-04-30之前的提交,包括当日
$ git log --until="2022-04-30"
commit 759b615e6e1192742976cae2c16589811aa0d814 (HEAD -> master)
Author: zhangsan <12345@qq.com>
Date:   Sat Apr 30 17:58:38 2022 +0800

    initial project version

4. 撤消操作

  1. 提交后,发现漏掉了几个文件没有添加,或者提交信息写错了,可以像下面这样操作:
$ git commit -m 'initial commit' # 上一次提交
$ git add forgotten_file # 暂存forgotten_file文件
$ git commit --amend # 提交forgotten_file文件,代替上一次提交的结果,最终只有一次提交

git commit --amend命令会将暂存区中的文件提交。在上次提交后,如果未做任何修改,那么快照会保持不变,修改的只是提交信息。第二次提交将代替第一次提交的结果,最终只有一次提交。

  1. 使用git add命令暂存a.txt文件后,可以使用下面的命令取消暂存的a.txt文件:
git reset HEAD a.txt
  1. 提交a.txt后,对a.txt进行修改,可以使用下面的命令撤消对文件的修改,还原成上次提交时的样子:
$ git checkout -- a.txt # 一个危险的命令,对a.txt在本地的任何修改都会消失

5. 打标签

Git 支持两种标签:

  • 附注标签(annotated): 是存储在 Git 数据库中的一个完整对象,它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间,此外还有一个标签信息,并且可以使用 GNU Privacy Guard(GPG)签名并验证。通常会建议创建附注标签,这样可以拥有以上所有信息。
  • 轻量标签(lightweight): 轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。如果只是想用一个临时的标签,或者因为某些原因不想要保存附注标签中的信息,可以用轻量标签。

5.1 列出标签

使用git tag命令以字母顺序列出已有的标签(可带上可选的 -l 选项 --list):

$ git tag
v0.1.0
v0.10.0
v0.11.0
v0.12.0
......

按照特定的模式查找标签:

$ git tag -l "v0.27*"
v0.27.0
v0.27.0-rc1
v0.27.0-rc2
v0.27.0-rc3
v0.27.1
v0.27.10
v0.27.2
v0.27.3
v0.27.4
v0.27.5
v0.27.6
v0.27.7
v0.27.8
v0.27.9

5.2 创建附注标签

在运行 tag 命令时指定 -a 选项创建附注标签,-m 选项指定了一条将会存储在标签中的信息(如果没有为附注标签指定一条信息,Git 会启动编辑器要求你输入信息):

$ git tag -a v1.0 -m 'version 1.0'

通过使用 git show 命令可以看到 打标签者的信息、打标签的日期时间、附注信息、具体的提交信息。

$ git show v1.0
tag v1.0
Tagger: zhangsan <12345@qq.com> # 打标签者的信息
Date:   Sun May 1 22:18:35 2022 +0800 # 打标签的日期时间

version 1.0 # 附注信息

# 具体的提交信息
commit 0dc3e6247ed13aa0d568bd1ec31ac6e00172c01a (HEAD -> master, tag: v1.0)
Author: zhangsan <12345@qq.com>
Date:   Sun May 1 21:14:51 2022 +0800

    new a.txt

diff --git a/a.txt b/a.txt
new file mode 100644
index 0000000..577fcb1
--- /dev/null
+++ b/a.txt
@@ -0,0 +1 @@
+this is git demo

v1.0

5.3 创建附注标签

轻量标签本质上是将提交校验和存储到一个文件中——没有保存任何其他信息。创建轻量标签,不需要使用 -a-s-m 选项,只需要提供标签名字:

$ git tag -a v1.0-lw -m 'version 1.0-lw'
$ git tag
v1.0
v1.0-lw

这时,如果在标签上运行 git show,不会看到额外的标签信息,只会显示出提交信息:

$ git show v1.0-lw
tag v1.0-lw
Tagger: zhangsan <12345@qq.com>
Date:   Sun May 1 22:35:51 2022 +0800

version 1.0-lw

commit 0dc3e6247ed13aa0d568bd1ec31ac6e00172c01a (HEAD -> master, tag: v1.0-lw, tag: v1.0)
Author: zhangsan <12345@qq.com>
Date:   Sun May 1 21:14:51 2022 +0800

    new a.txt

diff --git a/a.txt b/a.txt
new file mode 100644
index 0000000..577fcb1
--- /dev/null
+++ b/a.txt
@@ -0,0 +1 @@
+this is git demo

5.4 后期打标签

可以对过去的提交打标签。 假设提交历史是这样的:

$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

假设在 v1.2 时(在 “updated rakefile” 提交),忘记给项目打标签,可以在命令的末尾指定提交的校验和,补上标签:

$ git tag -a v1.2 9fceb02
$ git tag
v0.1
v1.2
v1.3
v1.4
v1.4-lw
v1.5

$ git show v1.2
tag v1.2
Tagger: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Feb 9 15:32:16 2009 -0800

version 1.2
commit 9fceb02d0ae598e95dc970b74767f19372d61af8
Author: Magnus Chacon <mchacon@gee-mail.com>
Date:   Sun Apr 27 20:43:35 2008 -0700

    updated rakefile
...

5.5 删除标签

可以使用以下命令删除一个本地标签:

$ git tag -d v1.0-lw
Deleted tag 'v1.0-lw' (was b81a375)
举报

相关推荐

0 条评论