《Pro Git》Git基础笔记
阅读原文时间:2023年08月11日阅读:1

获取Git仓库

$ git init

该命令会创建一个名为.git的隐藏文件。

$ git clone <url>
# 例如 git clone https://github.com/vuejs/vue
$ git clone <url> [newname]
# 自定义本地仓库的名字

Git支持多种数据传输协议:http://git://或者SSH

默认情况下,Git会将远程仓库设置为名为"origin"的远程仓库,并且会自动将您克隆的默认分支(通常是"master"或"main")设置为当前工作分支。

记录每次更新到仓库

初次克隆的仓库的工作目录下的所有文件都属于已跟踪文件,并处于未修改状态。

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

上面提示说明所有已跟踪文件无任何修改。

Git之前默认分支名是master,后来改为main关于github默认分支名改为main后可能的处理

$ git add <文件名或目录路径>

这时使用git status命令,会提示Changes to be commited,紧跟下面的文件则是已跟踪、已暂存状态。

使用git status命令出现的Changes not staged for commit提示是说明该提示下面的文件已跟踪且内容发生变,但未提交到暂存区,这时使用git add提交到暂存区即可。

使用-s--short选项可以简化状态输出:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

注意状态有两列。

  • ??:新添加的未跟踪文件。
  • 空格:未修改。
  • A空格:新添加到暂存区的文件。
  • 空格M:工作区中已修改但未暂存的文件。
  • M空格:已修改且已暂存。
  • MM:已修改,暂存后又作了修改但未暂存。
  • R:文件已被重命名。
  • D:文件已被删除。

一般我们不希望项目编译产物和日志文件等被列入未跟踪文件。我们可以创建一个.gitignore文件,列出想要忽略的文件模式。

.gitignore的规范格式如下:

  • 空行和以#开头的行都会被忽略。
  • 可以使用glob模式匹配。
  • 匹配模式可以以/开头防止递归。
  • 匹配模式可以以/结尾指定目录。
  • 在模式前加!可以忽略除指定模式以外的文件或目录。

Glob 语法及解析

使用git statusgit diff可以查看已暂存、未暂存的文件,只不过git diff以文件补丁形式更具体展示哪些行发生了改变。

git diff比较的是工作目录中当前文件和暂存区域快照之间的差异。 也就是修改之后还没有暂存起来的变化内容。

若要查看已暂存待提交的内容,可以使用git diff --staged命令。

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's
  • diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md:表示正在比较的文件是 CONTRIBUTING.md

  • index 8ebb991..643e24f 100644:显示了被比较文件的索引信息。

  • --- a/CONTRIBUTING.md:表示原始版本的文件。

  • +++ b/CONTRIBUTING.md:表示修改后的版本的文件。

  • @@ -65,7 +65,8 @@:表示修改发生在原始文件的第65行,同时在修改后的文件的第65行开始。

  • -merged in.:表示从原始版本中删除了 merged in. 这行。

  • +merged in. Also, split your changes into comprehensive chunks if your patch is:表示在修改后的版本中添加了 merged in. Also, split your changes into comprehensive chunks if your patch is 这行。

  • +longer than a dozen lines.:表示在修改后的版本中添加了 longer than a dozen lines. 这行。

    $ git commit

执行上面命令会启动你选择的文本编辑器来输入提交说明。

追加-v选项查看具体修改。

追加-m选项可以将提交信息与命令放在同一行。

执行完后,会提示当前所在分支,本次提交的完整校验和,本次提交中有多少文件修订过以及多少行添加或删除。

Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤。

移除文件分为从磁盘移除和从暂存区移除。

如果是从磁盘移除,我们先手动删除文件,运行git status时会提示删除文件操作未暂存。然后使用git rm <文件或路径>记录此次操作。若要删除的文件之前修改过或已放入暂存区,则必须使用-f选项强制删除。

如果从暂存区移除但仍保存在当前工作目录中,使用git rm --cached <文件或路径>

移动文件使用git mv <源文件或路径> <目的文件或路径>

git mv相当于下面三条命令:

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

git mv可以用于重命名文件。

查看提交历史

不传入任何参数的默认情况下,git log 会按时间先后顺序列出所有的提交,最近的更新排在最上面。

# 常规形式
$ git log
# -p 或 -patch 选项,增加补丁形式
$ git log -p
# --stat 选项,展示简略统计信息
$ git log --stat
# --pretty = oneline,展示简略统计信息
$ git log --pretty = oneline
# 定制记录的显示格式
$ git log --pretty = format:"%h - %an,ar%:s%"

git log --pretty = format常用选项:

选项

说明

%H

提交的完整哈希值

%h

提交的简写哈希值

%T

树的完整哈希值

%t

树的简写哈希值

%P

父提交的完整哈希值

%p

父提交的简写哈希值

%an

作者名字

%ae

作者的电子邮件地址

%ad

作者修订日期(可以用 --date=选项 来定制格式)

%ar

作者修订日期,按多久以前的方式显示

%cn

提交者的名字

%ce

提交者的电子邮件地址

%cd

提交日期

%cr

提交日期(距今多长时间)

%s

提交说明

git log --pretty=format:%h %s" --graph的执行结果如下:

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
*  5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
*  11d191e Merge branch 'defunkt' into local

*表示一次提交,竖线 (|) 代表一个分支,斜线 (/) 和反斜线 (\) 表示分支的合并。

限制git log输出的选项:

选项

说明

-<n>

仅显示最近的 n 条提交。

--since, --after

仅显示指定时间之后的提交。

--until, --before

仅显示指定时间之前的提交。

--author

仅显示作者匹配指定字符串的提交。

--committer

仅显示提交者匹配指定字符串的提交。

--grep

仅显示提交说明中包含指定字符串的提交。

-S

仅显示添加或删除内容匹配指定字符串的提交。

撤销操作

$ git commit --amend

执行该命令,如果自上次以来未做任何修改,那么快照保持不变,只修改提交信息。

而如果存在修改,这次提交会覆盖上次提交。

$ git reset HEAD <文件>


$ git checkout -- <file>

远程仓库的使用

git remote: 显示当前仓库已配置的所有远程仓库的简写名称。。默认名字是origin

git remote -v: 显示当前仓库已配置的所有远程仓库的简写名称和对应的URL。这会显示每个远程仓库的读取和写入的URL,如果你克隆了一个仓库,通常会看到一个名为"origin"的默认远程仓库。

git remote add <remote-name> <remote-url>: 添加一个新的远程仓库,并指定它的简写名称和URL。

$ git fetch <remote-name>

git fetch命令用于从远程仓库下载最新的提交历史,但不会自动合并或更新您的工作目录。它只会将远程仓库的变更下载到本地,并将它们存储在名为"origin"(默认远程仓库名)的分支中,例如origin/master表示远程仓库的master分支。

$ git pull <remote-name> <branch-name>

git pull命令用于从远程仓库获取更新并自动合并到当前分支中。它实际上是git fetchgit merge两个命令的组合。首先,它会执行git fetch来获取远程仓库的更新,然后将这些更新自动合并到当前分支中。

$ git push <remote-name> <branch>

git push将本地代码或修改推送到远程仓库的分支。

注意:执行git push前,确保拥有服务器的写入权限以及本地分支与远程分支之间没有冲突(即之前没有人推送过),否则你的推送将被拒绝,必须先抓取其他人的工作并合并到你的工作中才能推送。

命令格式:

$ git remote show <remote>

示例输出:

* remote origin
  Fetch URL: https://github.com/username/repo.git
  Push  URL: https://github.com/username/repo.git
  HEAD branch: main
  Remote branches:
    main       tracked
    feature-A  tracked
    feature-B  new (next fetch will store in remotes/origin)
  Local branches configured for 'git pull':
    main       merges with remote main
    feature-A  merges with remote feature-A
  Local refs configured for 'git push':
    main       pushes to main       (up to date)
    feature-A  pushes to feature-A  (local out of date)

示例分析:

  • remote origin:显示该远程仓库的名称,即"origin"。

  • Fetch URLPush URL:显示该远程仓库的获取(fetch)URL和推送(push)URL。这里都为"https://github.com/username/repo.git"。

  • HEAD branch: main:指示远程仓库的默认分支是"main"分支。

  • Remote branches:显示所有在远程仓库中存在的分支,并且标记它们是否被本地跟踪(tracked)。

  • Local branches configured for 'git pull':显示与远程仓库分支进行合并(merge)的本地分支。

  • Local refs configured for 'git push':显示用于推送(push)到远程仓库的本地引用(通常是分支)。

    重命名

    $ git remote rename

    删除

    $ git remote remove 或 git remote rm

打标签

在Git中,你可以给特定的提交(Commit)来使用标签(Tag)打上标记,类似于一个代码版本的快照。标签通常用于标识重要的里程碑、版本发布或稳定版本,以便以后更容易地找到和访问这些特殊地提交。

命令:git tag以字母顺序列出标签。

按照特定模式查找标签:git tag -l <glob模式>

Git有两种标签:轻量标签(lightweight)和附注标签(annotated)。

轻量标签

轻量标签是对特定提交的引用。只包含提交信息。

命令:git tag <tagname> [commit-id]。不加提交号默认给当前分支的最新提交打标签。

附注标签

附注标签是Git数据库中一个完整对象,是可以被校验的,包含了打标签者的信息和一个标签信息。

命令:git remote -a <tag-name> -m "Tag message" [commit-id]。不加提交号默认给当前分支的最新提交打标签。

git push不会将标签推送到远程服务器上。这需要我们显示的推送标签:

  1. 推送所有标签:git push origin --tags
  2. 推送指定标签:git push origin <tagname>
  • 删除本地标签:git tag -d <tagname>
  • 更新远程仓库标签:git push <remote> :refs/tags/<tagname>git push origin --delete <tagname>

git checkout可以用于检出指定的提交,并将仓库的 HEAD 指向该提交。这样会处于“分离 HEAD”状态,意味着您不再位于任何分支上。通常,您不会在这种状态下进行修改,因为新提交将没有分支引用,会很难找到和维护。

如果想检出旧标签并且需要更改旧版本中的内容,那么就需要新建一个分支:git checkout -b <branch-name> <tagname>

Git别名

Git提供给命令提供别名的功能。

命令格式:git config --global alias.<alias-name> <git-command>