Git 基础——《Pro Git》
⭐获取 Git 仓库
获取 Git 仓库有两种方式:
- 将未进行版本控制的本地目录转换为 Git 仓库。
- 从其他服务器克隆一个已存在的 Git 仓库。
在已存在目录中初始化 Git 仓库
- 进入目标目录
-
- 在 Linux 上:
$ cd /home/user/my_project
- 在 macOS 上:
$ cd /Users/user/my_project
- 在 Linux 上:
$ cd /c/user/my_project
- 在 Linux 上:
- 执行初始化:
$ git init
克隆现有的 Git 仓库
- 克隆仓库命令:
$ git clone https://github.comlibgit2/libgit2
- 克隆并修改名称命令:
$ git clone https://github.comlibgit2/libgit2/mylibgit
⭐记录每次更新到仓库
工作目录下的每一个文件只有两种状态:已跟踪 或 未跟踪
- 已跟踪:被纳入版本控制的的文件,在上一次快照中有它们的记录。已跟踪的文件的状态可能为:未修改、已修改、已暂存。即已经知道的文件。
- 未跟踪:除已跟踪以外的文件。
检查当前文件状态——git status
可以用 git status 命令查看哪些文件处于什么状态。
- 克隆仓库后使用:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
- 新建 Git 仓库后使用:
跟踪新文件——git add
- 使用命令
git add
开始跟踪一个文件。 所以,要跟踪README
文件,运行:
$ git add README
- 此时再运行
git status
命令,会看到README
文件已被跟踪,并处于暂存状态:
$ git 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
- 只要在
Changes to be committed
这行下面的,就说明是已暂存状态。 如果此时提交,那么该文件在你运行git add
时的版本将被留存在后续的历史记录中。 git add
命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。
暂存已修改的文件——git add
git add
是个多功能命令:应理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到新项目中”。
- 开始跟踪新文件
- 把已跟踪的文件放到暂存区
- 合并时把有冲突的文件标记为已解决状态
git commit
时,提交的文件是最后一次运行git add
时的版本,而不是git commit
时的版本。所以一个文件可能即在 暂存区 又在 非暂存区。
状态简览——git status -s
Git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改。 如果你使用 git status -s 命令或 git status --short 命令,你将得到一种格式更为紧凑的输出。
$ git status -sM README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
- 左列:暂存区的状态,右列:工作区的状态。
??
:新添加且未追踪的文件。A
(Added):新添加到暂存区的文件。M
(Modified):修改过的文件。
M README
-
- 左列为空,说明
README
文件在暂存区没有更改。 - 右列是
M
,说明文件在工作区中被修改,但尚未暂存。
- 左列为空,说明
MM Rakefile
-
- 左列是
M
,说明Rakefile
文件的某些更改已经被添加到暂存区。 - 右列是
M
,说明文件在工作区中又有了新的更改,但这些更改尚未被添加到暂存区。
- 左列是
A lib/git.rb
-
- 左列是
A
,说明lib/git.rb
是一个新文件,已被添加到暂存区。 - 右列为空,说明该文件在工作区没有未暂存的更改。
- 左列是
?? LICENSE.txt
-
- 双问号
??
表示LICENSE.txt
是一个新文件,尚未被 Git 跟踪(未被添加到暂存区)。
- 双问号
忽略文件——.gitignore
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore
的文件,列出要忽略的文件的模式。 来看一个实际的 .gitignore
例子:
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o
或 .a
结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。 第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。 要养成一开始就为你的新仓库设置好 .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
等。
我们再看一个 .gitignore
文件的例子:
# 忽略所有的 .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
Tip | GitHub 有一个十分详细的针对数十种项目及语言的 |
Note | 在最简单的情况下,一个仓库可能只根目录下有一个 多个 |
查看已暂存和未暂存的修改——git diff
- 通常可能会用它来回答这两个问题:
- 当前做的哪些更新尚未暂存?
-
- 要查看尚未暂存的文件更新了哪些部分,不加参数直接输入
git diff
- 注意,git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你一下子暂存了所有更新过的文件,运行
git diff
后却什么也没有,就是这个原因。
- 要查看尚未暂存的文件更新了哪些部分,不加参数直接输入
- 有哪些更新已暂存并准备好下次提交?
-
- 若要查看已暂存的将要添加到下次提交里的内容,可以用
git diff --staged
命令。 这条命令将比对已暂存文件与最后一次提交的文件差异:
- 若要查看已暂存的将要添加到下次提交里的内容,可以用
- 虽然
git status
已经通过在相应栏下列出文件名的方式回答了这个问题,但git diff
能通过文件补丁的格式更加具体地显示哪些行发生了改变。
Note | Git Diff 的插件版本 在本书中,我们使用 |
提交更新——git commit
- 现在的暂存区已经准备就绪,可以提交了。 在此之前,请务必确认还有什么已修改或新建的文件还没有
git add
过, 否则提交的时候不会记录这些尚未暂存的变化。 这些已修改但未暂存的文件只会保留在本地磁盘。 所以,每次准备提交前,先用git status
看下,你所需要的文件是不是都已暂存起来了, 然后再运行提交命令git commit
:
$ git commit
- 这样会启动你选择的文本编辑器来输入提交说明。
Note | 启动的编辑器是通过 Shell 的环境变量 |
- 编辑器会显示类似下面的文本信息(本例选用 Vim 的屏显方式展示):
# Please 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
的输出,放在注释行里,另外开头还有一个空行,供你输入提交说明。 你完全可以去掉这些注释行,不过留着也没关系,多少能帮你回想起这次更新的内容有哪些。
Note | 更详细的内容修改提示可以用 |
- 退出编辑器时,Git 会丢弃注释行,用你输入的提交说明生成一次提交。
- 另外,你也可以在
commit
命令后添加-m
(message) 选项,将提交信息与命令放在同一行,如下所示:
$ git commit -m "Story 182: Fix benchmarks for speed"
[master 463dc4f] Story 182: Fix benchmarks for speed2 files changed, 2 insertions(+)create mode 100644 README
- 可以看到,提交后它会告诉你,当前是在哪个分支(
master
)提交的,本次提交的完整 SHA-1 校验和是什么(463dc4f
),以及在本次提交中,有多少文件修订过,多少行添加和删改过。 - 请记住,提交时记录的是放在暂存区域的快照。 任何还未暂存文件的仍然保持已修改状态,可以在下次提交时纳入版本管理。 每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。
跳过使用暂存区域——git commit -a
- Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给
git commit
加上-a
选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过git add
步骤:
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks1 file changed, 5 insertions(+), 0 deletions(-)
- 这很方便,但是要小心,有时这个选项会将不需要的文件添加到提交中。
移除文件——git rm
- 要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用
git rm
命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
- 如果只是简单地从工作目录中手工删除文件,运行
git status
时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到:
$ 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.mdno changes added to commit (use "git add" and/or "git commit -a")
- 然后再运行
git rm
记录此次移除文件的操作:
$ git rm PROJECTS.md
rm 'PROJECTS.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)deleted: PROJECTS.md
- 下一次提交时,该文件就不再纳入版本管理了。 如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项
-f
(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。
- 另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加
.gitignore
文件,不小心把一个很大的日志文件或一堆.a
这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用--cached
选项:
$ git rm --cached README
git rm
命令后面可以列出文件或者目录的名字,也可以使用glob
模式。比如:
$ git rm log/\*.log
- 注意到星号
*
之前的反斜杠\
, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除log/
目录下扩展名为.log
的所有文件。 类似的比如:
$ git rm \*~
- 该命令会删除所有名字以
~
结尾的文件。
移动文件——git mv <file_from> <file_to>
- 当你看到 Git 的
mv
命令时一定会困惑不已。 要在 Git 中对文件改名,可以这么做:
$ git mv file_from file_to
- 它会恰如预期般正常工作。 实际上,即便此时查看状态信息,也会明白无误地看到关于重命名操作的说明:
$ git 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
就相当于运行了下面三条命令:
$ mv README.md README
$ git rm README.md
$ git add README
- 如此分开操作,Git 也会意识到这是一次重命名,所以不管何种方式结果都一样。 两者唯一的区别在于,
git mv
是一条命令而非三条命令,直接使用git mv
方便得多。 不过在使用其他工具重命名文件时,记得在提交前git rm
删除旧文件名,再git add
添加新文件名。
查看提交历史——git log
不传入任何参数的默认情况下,git log
会按时间先后顺序列出所有的提交,最近的更新排在最上面。 正如你所看到的,这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。
常用的选项
- 常用选项表:
选项 | 说明 |
| 按补丁格式显示每个提交引入的差异。 |
| 显示每次提交的文件修改统计信息。 |
| 只显示 --stat 中最后的行数修改添加移除统计。 |
| 仅在提交信息后显示已修改的文件清单。 |
| 显示新增、修改、删除的文件清单。 |
| 仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 |
| 使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 |
| 在日志旁以 ASCII 图形显示分支与合并历史。 |
| 使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format(用来定义自己的格式)。 |
|
|
-p
(patch):比较有用的选项是-p
或--patch
,它会显示每次提交所引入的差异(按 补丁 的格式输出)。
-
- 也可以限制显示的日志条目数量,例如使用
-2
选项来只显示最近的两次提交 - 该选项除了显示基本信息之外,还附带了每次提交的变化。 当进行代码审查,或者快速浏览某个搭档的提交所带来的变化的时候,这个参数就非常有用了。
- 也可以限制显示的日志条目数量,例如使用
--stat
(statistic):提供每次提交的简略统计信息
-
--stat
选项在每次提交的下面列出所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或是添加了。 在每次提交的最后还有一个总结。
--pretty
:可以使用不同于默认格式的方式展示提交历史。
-
oneline
:会将每个提交放在一行显示,在浏览大量的提交时非常有用。short
,full
,fuller
:它们展示信息的格式基本一致,但是详尽程度不一。format
:可以定制记录的显示格式。 这样的输出对后期提取分析格外有用——因为你知道输出的格式不会随着 Git 的更新而发生改变
-
-
git log --pretty=format
常用的选项表:
-
选项 | 说明 |
| 提交的完整哈希值 |
| 提交的简写哈希值 |
| 树的完整哈希值 |
| 树的简写哈希值 |
| 父提交的完整哈希值 |
| 父提交的简写哈希值 |
| 作者名字 |
| 作者的电子邮件地址 |
| 作者修订日期(可以用 --date=选项 来定制格式) |
| 作者修订日期,按多久以前的方式显示 |
| 提交者的名字 |
| 提交者的电子邮件地址 |
| 提交日期 |
| 提交日期(距今多长时间) |
| 提交说明 |
--graph
:添加了一些 ASCII 字符串来形象地展示你的分支、合并历史。
限制输出选项
选项 | 说明 |
| 仅显示最近的 n 条提交。 |
| 仅显示指定时间之后的提交。(可以是类似 |
| 仅显示指定时间之前的提交。 |
| 仅显示作者匹配指定字符串的提交。 |
| 仅显示提交者匹配指定字符串的提交。 |
| 仅显示提交说明中包含指定字符串的提交。 |
| 仅显示添加或删除内容匹配指定字符串的提交。 非常有用的过滤器是 |
| 如果只关心某些文件或者目录的历史提交,可以在 git log 选项的最后指定它们的路径。 因为是放在最后位置上的选项,所以用两个短划线(--)隔开之前的选项和后面限定的路径名。 |
Note | 你可以指定多个 |
实例
来看一个实际的例子,如果要在 Git 源码库中查看 Junio Hamano 在 2008 年 10 月其间, 除了合并提交之外的哪一个提交修改了测试文件,可以使用下面的命令:
$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \--before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch
在近 40000 条提交中,上面的输出仅列出了符合条件的 6 条记录。
Tip | 隐藏合并提交 按照你代码仓库的工作流程,记录中可能有为数不少的合并提交,它们所包含的信息通常并不多。 为了避免显示的合并提交弄乱历史记录,可以为 |
撤销操作
重新提交——git commit --amend
- 有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有
--amend
选项的提交命令来重新提交。 - 这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。
- 最终你只会有一个提交——第二次提交将代替第一次提交的结果。
✍️:
- 当你在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个 新的提交 替换旧的提交, 理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
- 修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。
取消暂存的文件——git reset HEAD <file>
- 例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入
git add *
暂存了它们两个。用来只取消暂存两个中的一个。
✍️:
git reset
确实是个危险的命令,如果加上了--hard
选项则更是如此。 然而在上述场景中,工作目录中的文件尚未修改,因此相对安全一些。
撤销对文件的修改——git checkout --<file>
- 不想保留对某文件的修改。
✍️:
- 请务必记得
git checkout — <file>
是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。
总结
在 Git 中任何 已提交 的东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用 --amend
选项覆盖的提交也可以恢复 (阅读 数据恢复 了解数据恢复)。 然而,任何你未提交的东西丢失后很可能再也找不到了。
远程仓库的使用
为了能在任意 Git 项目上协作,你需要知道如何管理自己的远程仓库。 远程仓库是指托管在因特网或其他网络中的你的项目的版本库。 你可以有好几个远程仓库,通常有些仓库对你只读,有些则可以读写。 与他人协作涉及管理远程仓库以及根据需要推送或拉取数据。 管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不同的远程分支并定义它们是否被跟踪等等。
✍️远程仓库可以在你的本地主机上:
你完全可以在一个“远程”仓库上工作,而实际上它在你本地的主机上。 词语“远程”未必表示仓库在网络或互联网上的其它位置,而只是表示它在别处。 在这样的远程仓库上工作,仍然需要和其它远程仓库上一样的标准推送、拉取和抓取操作。
查看远程仓库——git remote
- 列出你指定的每一个远程服务器的简写。
- 如果你已经克隆了自己的仓库,那么至少应该能看到 origin ——这是 Git 给你克隆的仓库服务器的默认名字。
- 指定选项
-v
,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。
添加远程仓库——git remote add <shortname> <url>
- 运行
git remote add <shortname> <url>
添加一个新的远程 Git 仓库,同时指定一个方便使用的简写 - 如果指定了简写,以后可以用<shortname>代替整个 URL。如:
git fetch <shortname>
。
从远程仓库抓取与拉取——git fetch <remote> <branch>
, git pull <remote> <branch>
fetch
: 访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。pull
:
-
- 如果你的当前分支设置了跟踪远程分支, 那么可以用
git pull
命令来自动抓取后合并该远程分支到当前分支。 - 默认情况下,
git clone
命令会自动设置本地 master 分支跟踪克隆的远程仓库的master
分支(或其它名字的默认分支)。 运行git pull
通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。
- 如果你的当前分支设置了跟踪远程分支, 那么可以用
推送到远程仓库——git push <remote> <branch>
- 当你想要将
master
分支推送到origin
服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字), 那么运行这个命令就可以将你所做的备份到服务器: - 只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先抓取他们的工作并将其合并进你的工作后才能推送。
查看某个远程仓库——git show <remote>
- 它会列出远程仓库的 URL 与跟踪分支的信息。 这些信息非常有用,它告诉你正处于
master
分支,并且如果运行git pull
, 就会抓取所有的远程引用,然后将远程master
分支合并到本地master
分支。 它也会列出拉取到的所有远程引用。 - 这个命令列出了当你在特定的分支上执行
git push
会自动地推送到哪一个远程分支。 它也同样地列出了哪些远程分支不在你的本地,哪些远程分支已经从服务器上移除了, 还有当你执行git pull
时哪些本地分支可以与它跟踪的远程分支自动合并。 - 示例:
$ git remote show origin
* remote originURL: https://github.com/my-org/complex-projectFetch URL: https://github.com/my-org/complex-projectPush URL: https://github.com/my-org/complex-projectHEAD branch: masterRemote branches:master trackeddev-branch trackedmarkdown-strip trackedissue-43 new (next fetch will store in remotes/origin)issue-45 new (next fetch will store in remotes/origin)refs/remotes/origin/issue-11 stale (use 'git remote prune' to remove)Local branches configured for 'git pull':dev-branch merges with remote dev-branchmaster merges with remote masterLocal refs configured for 'git push':dev-branch pushes to dev-branch (up to date)markdown-strip pushes to markdown-strip (up to date)master pushes to master (up to date)
远程仓库的重命名与移除——git remote rename
, git remote remove
git remote rename
:修改一个远程仓库的简写名。 例如,想要将pb
重命名为paul
,可以用git remote rename
这样做:
$ git remote rename pb paul
$ git remote
origin
paul
-
- 值得注意的是这同样也会修改你所有远程跟踪的分支名字。 那些过去引用
pb/master
的现在会引用paul/master
。
- 值得注意的是这同样也会修改你所有远程跟踪的分支名字。 那些过去引用
git remote remove
:移除一个远程仓库——你已经从服务器上搬走了或不再想使用某一个特定的镜像了, 又或者某一个贡献者不再贡献了。
-
- 一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。
打标签——git tag
1. 列出标签
- 使用
git tag
查看所有标签。 - 可以使用
git tag -l "v1.8.5*"
按模式过滤标签。
2. 创建标签
- 附注标签:使用
git tag -a <tagname> -m "message"
创建,包含打标签者信息、时间、信息等。 - 轻量标签:使用
git tag <tagname>
创建,仅是指向某提交的引用,没有附加信息。
3. 后期打标签
- 通过
git tag -a <tagname> <commit-hash>
为过去的提交打标签。
4. 共享标签
- 使用
git push origin <tagname>
推送标签。 - 使用
git push origin --tags
推送所有标签。
5. 删除标签
- 本地删除标签:
git tag -d <tagname>
。 - 从远程删除标签:
git push origin :refs/tags/<tagname>
或git push origin --delete <tagname>
。
6. 检出标签
- 使用
git checkout <tagname>
检出标签,进入“分离头指针”状态。
Git 别名
Git 别名可以帮助简化命令,减少输入长度,使 Git 操作更加高效。你可以通过配置别名,将常用的长命令缩短为更直观的命令。
常见的 Git 别名配置示例
1. 基本命令简化
git config --global alias.co checkout
将git checkout
简化为git co
。git config --global alias.br branch
将git branch
简化为git br
。git config --global alias.ci commit
将git commit
简化为git ci
。git config --global alias.st status
将git status
简化为git st
。
2. 自定义实用别名
- 取消暂存文件
git config --global alias.unstage 'reset HEAD --'
使用 git unstage fileA
撤销暂存,等价于 git reset HEAD -- fileA
。
- 查看最后一次提交
git config --global alias.last 'log -1 HEAD'
使用 git last
查看最后一次提交记录。
3. 外部命令别名
- 运行外部工具
git config --global alias.visual '!gitk'
使用 git visual
打开 gitk
图形界面工具。
其他提示
- Git 别名本质上是将别名替换为实际命令,完全可以根据自己的习惯定义。
- 外部命令需要在别名前加上
!
,比如运行第三方工具或脚本。
相关文章:
Git 基础——《Pro Git》
⭐获取 Git 仓库 获取 Git 仓库有两种方式: 将未进行版本控制的本地目录转换为 Git 仓库。从其他服务器克隆一个已存在的 Git 仓库。 在已存在目录中初始化 Git 仓库 进入目标目录 在 Linux 上:$ cd /home/user/my_project在 macOS 上:$ c…...
数据结构与算法之二叉树: LeetCode 654. 最大二叉树 (Ts版)
最大二叉树 https://leetcode.cn/problems/maximum-binary-tree/ 描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值递归地在最大值 左边 的 子数组前缀上 构建左子树递归地在最大值…...
学习记录:C++宏定义包含多条语句,使用注意事项
应该使用 do - while(0) 结构的情况 在条件语句(如 if - else、switch - case)或循环语句(如 for、while、do - while)中使用宏: 当宏定义包含多条语句且会在上述语句中使用时,使用 do - while(0) 可确保…...
PHP 使用 Redis
PHP 使用 Redis PHP 是一种广泛使用的服务器端编程语言,而 Redis 是一个高性能的键值对存储系统。将 PHP 与 Redis 结合使用,可以为 Web 应用程序提供快速的读写性能和丰富的数据结构。本文将详细介绍如何在 PHP 中使用 Redis,包括安装、连接、基本操作以及一些高级应用。 …...
项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(五)
文章目录 一、学生管理模块功能实现1、添加学生功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、学生管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码…...
下载并安装MySQL
在Linux系统上下载并安装数据库(以MySQL为例)的步骤如下: 一、下载MySQL 访问MySQL官网 打开浏览器,访问MySQL的官方网站:https://www.mysql.com/。 进入下载页面 在MySQL官网首页,找到并点击“Downloads…...
【C++入门】详解(中)
目录 💕1.函数的重载 💕2.引用的定义 💕3.引用的一些常见问题 💕4.引用——权限的放大/缩小/平移 💕5. 不存在的空引用 💕6.引用作为函数参数的速度之快(代码体现) Ǵ…...
计算机视觉算法实战——车道线检测
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 车道线检测是计算机视觉领域的一个重要研究方向,尤其在自动驾驶和高级驾驶辅助…...
基于http协议的天气爬虫
该系统将基于目前比较流行的网络爬虫技术, 对网站上的天气数据进行查询分析, 最终使客户能够通过简单的操作, 快速, 准确的获取目标天气数据。主要包括两部分的功能, 第一部分是天气数据查询, 包括时间段数…...
自然语言处理基础:全面概述
自然语言处理基础:全面概述 什么是NLP及其重要性、NLP的核心组件、NLU与NLG、NLU与NLG的集成、NLP的挑战以及NLP的未来 自然语言处理(NLP)是人工智能(AI)中最引人入胜且具有影响力的领域之一。它驱动着我们日常使用的…...
软件架构考试基础知识 002:进程的状态与其切换
进程状态转换的说明 在操作系统中,进程的状态表示其当前的执行情况和资源占用情况。进程状态的转换反映了操作系统如何管理和调度进程。以下是进程状态转换的说明: 1. 三态模型(Three-state Model) 三态模型是最基础的进程状态模…...
【Linux系列】Curl 参数详解与实践应用
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
VsCode对Arduino的开发配置
ps:我的情况是在对esp32进行编译、烧录时,找不到按钮,无法识别Arduino文件,适合已经有ini文件的情况。 1.在vscode中安装拓展 2.打开设置,点击右上角,转到settings.json文件 3.复制以下代码并保存 {"…...
【Pandas】pandas Series rtruediv
Pandas2.2 Series Binary operator functions 方法描述Series.add()用于对两个 Series 进行逐元素加法运算Series.sub()用于对两个 Series 进行逐元素减法运算Series.mul()用于对两个 Series 进行逐元素乘法运算Series.div()用于对两个 Series 进行逐元素除法运算Series.true…...
VUE3 自定义指令的介绍
自定义指令的概述 在 Vue 中,自定义指令是一种机制,允许开发者在模板中直接操作 DOM 元素,执行一些低级别的操作。Vue 提供了几个内置指令(如 v-if、v-for、v-model 等),但当我们需要一些特定功能时&#…...
RedisDB双机主从同步性能测试
安装redisDB 主节点 apt install redis-server修改配置 /etc/redis/redis.conf bind 0.0.0.0save "" # 禁止RDB持久化 #save 900 1 #save 300 10 #save 60 10000appendonly no # 禁止AOF持久化重启服务 systemctl restart redis-server从节点配置文件 bind 0.…...
【汇编】x86汇编编程寄存器资源心中有数
1. CPU状态及控制寄存器 TR,GDTR,LDTRcr0-cr3EFLAGS 等等 2. 业务计算寄存器(我起的名字) 业务寄存器用于访问内存、参数传递、数据传递、计算。 段寄存器6个: cs,ds,es,ss&…...
一.项目课题 <基于TCP的文件传输协议实现>
客户端代码 需要cJSON.c文件和cJSON.h文件 在这里插入代码片#include "myheadth.h" #include "myfun.h"#define TIME 10 int sockfd; void heartbeat(int signum) {cJSON* root cJSON_CreateObject();cJSON_AddStringToObject(root,"request"…...
【数据结构学习笔记】19:跳表(SkipList)
介绍 跳表是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)时间完成查找、插入、删除的数据结构,相比于树形结构优点就是很好写(所以也用于实现Redis ZSet)。其核心思想就是维护一个元素有序的,能随机提升索引层数的链表。最下面一…...
Cocos Creator 3.8 修改纹理像素值
修改的代码: import { _decorator, Component, RenderTexture, Sprite, Texture2D, ImageAsset, SpriteFrame, Vec2, gfx, director, log, math, v2 } from cc;const { ccclass, property } _decorator;ccclass(GradientTransparency) export class GradientTrans…...
【Linux】网络层
目录 IP协议 协议头格式 网段划分 2中网段划分的方式 为什么要进行网段划分 特殊的IP地址 IP地址的数量限制 私有IP地址和公有IP地址 路由 IP协议 在通信时,主机B要把数据要给主机C,一定要经过一条路径选择,为什么经过路由器G后&…...
单片机Day1
目录 一.什么是单片机? 二.单片机的组成 三.封装形式 四.优势 五.分类 通用型: 专用型: 按处理的二进制位可以分为: 六.应用: 七.发展趋势 1.增加CPU的数据总线宽度。 2.存储器的发展。 3.片内1/0的改进 …...
django基于 Python 的考研学习系统的设计与实现
以下是对Django基于Python的考研学习系统的设计与实现: 一、系统概述 Django基于Python的考研学习系统是一个为考研学子提供一站式学习辅助的平台。它整合了丰富的学习资源、学习计划制定、学习进度跟踪以及交流互动等功能,旨在满足考生在备考过程中的…...
openCvSharp 计算机视觉图片找茬
一、安装包 <PackageReference Include"OpenCvSharp4" Version"4.10.0.20241108" /> <PackageReference Include"OpenCvSharp4.runtime.win" Version"4.10.0.20241108" /> 二、准备两张图片 三、编写代码 using OpenCv…...
深入学习 Python 爬虫:从基础到实战
深入学习 Python 爬虫:从基础到实战 前言 Python 爬虫是一个强大的工具,可以帮助你从互联网上抓取各种数据。无论你是数据分析师、机器学习工程师,还是对网络数据感兴趣的开发者,爬虫都是一个非常实用的技能。在本文中ÿ…...
【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)
【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection) 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集,可以获取数据库中未授权的数据。这种注入技术要…...
【DAPM杂谈之一】DAPM作用与内核文档解读
本文主要分析DAPM的设计与实现 内核的版本是:linux-5.15.164,下载链接: Linux内核下载 主要讲解有关于DAPM相关的知识,会给出一些例程并分析内核如何去实现的 /****************************************************************…...
计算机网络之---防火墙与入侵检测系统(IDS)
防火墙与入侵检测系统(IDS) 防火墙(Firewall) 和 入侵检测系统(IDS, Intrusion Detection System) 都是网络安全的关键组件,但它们的作用、功能和工作方式有所不同。 防火墙 防火墙是网络安全的一种设备或软件&#…...
HTML中meta的用法
学习网络空间安全专业,每个人有每个人的学法和选择。不论他选择什么,哪都是他自己的选择,这就是大多数视频教学的博主教学的步骤都不同原因之一。有人选择丢掉大部分理论直接学习网安,而我,选择了捡起大部分理论学习网…...
前端学习-事件流,事件捕获,事件冒泡以及阻止冒泡以及相应案例(二十八)
目录 前言 事件流与两个阶段说明 说明 事件捕获 目标 说明 事件冒泡 目标 事件冒泡概念 简单理解 阻止冒泡 目标 语法 注意 综合示例代码 总结 前言 梳洗罢,独倚望江楼。过尽千帆皆不是,斜晖脉脉水悠悠。肠断白蘋洲 事件流与两个阶段说明…...
国产OS移植工业物联网OPC-UA协议
国家对于工业互联网、基础软件等关键领域的重视程度不断提升,为工业领域的硬件与软件国产化提供了坚实的政策保障。国产操作系统对工业物联网的一些重要领域的适配支持一直在推进。本次通过国产UOS系统移植测试OPC-UA协议。 1、OPC UA通信协议 OPC UA 协议…...
第25章 汇编语言--- 信号量与互斥锁
信号量(Semaphore)和互斥锁(Mutex,全称Mutual Exclusion Object)是两种用于管理对共享资源的访问的同步机制。它们在多线程或多进程编程中非常重要,可以确保同一时间只有一个线程或进程能够访问特定的资源&…...
写个自己的vue-cli
写个自己的vue-cli 1.插件代码2. 发布流程3. 模板代码讲解3.1 vue2模板的运行流程:3.2 vue3模板的运行流程: 1.插件代码 写一个自己的vue-cli插件 插件地址:插件地址 流程: 实现简单版 vue-cli 步骤文档1. 项目初始化 - 创建项目文件夹 qsl-vue-cli - …...
使用new Vue创建Vue 实例并使用$mount挂载到元素上(包括el选项和$mount区别)
new Vue({...}) 是创建一个新的 Vue 实例的方式。你可以通过传递一个选项对象来配置这个实例。常见的选项包括: •data:定义组件的数据属性。 •el:指定 Vue 实例应该挂载到哪个 DOM 元素上(通常是一个选择器字符串,如…...
【理论】测试框架体系TDD、BDD、ATDD、MBT、DDT介绍
一、测试框架是什么 测试框架是一组用于创建和设计测试用例的指南或规则。框架由旨在帮助 QA 专业人员更有效地测试的实践和工具的组合组成。 这些指南可能包括编码标准、测试数据处理方法、对象存储库、存储测试结果的过程或有关如何访问外部资源的信息。 A testing framewo…...
机器学习全流程解析:数据导入到服务上线全阶段介绍
目录 1. 数据导入 2. 数据预处理 3. 超参数搜索与优化 4. 模型训练 5. 模型评估 6. 模型压缩与优化 7. 模型注册与版本管理 8. 服务上线与部署 总结 1. 数据导入 数据源:数据库、文件系统、API等。数据格式:CSV、JSON、SQL 数据库表、Parquet …...
shell脚本练习
1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容,不存在则创建一个文件将创建时间写入。 if [ -f /tmp/size.log ];thencat /tmp/size.logelsestat exist.sh | awk -F: "NR5" > /tmp/size.logfi 2、写一个 shel1 脚本,实现批量添加…...
金山WPS Android面试题及参考答案
说说你所知道的所有集合?并阐述其内部实现。 在 Android 开发(Java 语言基础上)中有多种集合。 首先是 List 集合,主要包括 ArrayList 和 LinkedList。 ArrayList 是基于数组实现的动态数组。它的内部有一个数组来存储元素,当添加元素时,如果数组容量不够,会进行扩容操作…...
分类模型为什么使用交叉熵作为损失函数
推导过程 让推理更有体感,进行下面假设: 假设要对猫、狗进行图片识别分类假设模型输出 y y y,是一个几率,表示是猫的概率 训练资料如下: x n x^n xn类别 y ^ n \widehat{y}^n y n x 1 x^1 x1猫1 x 2 x^2 x2猫1 x …...
高等数学学习笔记 ☞ 单调性、凸凹性、极值、最值、曲率
1. 单调性 1. 单调性定义:设函数在区间上有定义,对于区间上任意两点,若: ①:当时,恒有,则称函数在区间上单调递增。 ②:当时,恒有,则称函数在区间上单调递减…...
【操作系统】详解操作系统及其结构
考察频率难度40%--60%⭐⭐ 这又是一类面试考察题,是关于操作系统的一些概念问题,很少会单独拎出来作为一个问题进行提问,但却是必须要掌握的。因为如果这个你不会,其他的问题就已经没有回答的必要了。 什么是操作系统࿱…...
primitive 的 Appearance编写着色器材质
import { nextTick, onMounted, ref } from vue import * as Cesium from cesium import gsap from gsaponMounted(() > { ... })// 1、创建矩形几何体,Cesium.RectangleGeometry:几何体,Rectangle:矩形 let rectGeometry new…...
自动化测试框架搭建-接口数据结构设计
目的 确认数据库如何保存接口数据,既有扩展性,数据又全又好用 根据用途设计数据库字段 区分环境:可以明确当前接口自动化用例,是在哪个环境需要执行的 模块:微服务架构,不同测试同学负责不同的模块&…...
Python自学 - 使用自定义异常
<< 返回目录 1 Python自学 - 使用自定义异常 在Python中, 不仅可以使用内置异常,用户还可以创建自己的异常。自定义异常需要继承自Exception类或其子类,如下是一个自定义异常示例: 示例1:一个简单的自定义异常…...
微信小程序-Docker+Nginx环境配置业务域名验证文件
在实际开发或运维工作中,我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件,用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx,就需要将该验证文件正确地映射(挂载)到容器中,并…...
“AI智能服务平台系统,让生活更便捷、更智能
大家好,我是资深产品经理老王,今天咱们来聊聊一个让生活变得越来越方便的高科技产品——AI智能服务平台系统。这个系统可是现代服务业的一颗璀璨明珠,它究竟有哪些魅力呢?下面我就跟大家伙儿闲聊一下。 一、什么是AI智能服务平台系…...
【PPTist】插入形状、插入图片、插入图表
一、插入形状 插入形状有两种情况,一种是插入固定的形状, 一种是插入自定义的形状。 插入固定的形状时,跟上一篇文章 绘制文本框 是一样一样的,都是调用的 mainStore.setCreatingElement() 方法,只不多传的类型不一…...
云集电商:数据库的分布式升级实践|OceanBase案例
电商行业对数据库有哪些需求 云集电商作为一家传统电商企业,业务涵盖了美妆个护、服饰、水果生鲜、健康保健等多个领域,在创立四年后在纳斯达克上市(股票代码:YJ)。与京东、淘宝、拼多多等电商平台不同,云…...
OOM排查思路
K8S 容器的云原生生态,改变了服务的交付方式,自愈能力和自动扩缩等功能简直不要太好用。 有好的地方咱要夸,不好的地方咱也要说,真正的业务是部署于容器内部,而容器之外,又有一逻辑层 Pod 。 对于容器和…...
Q_OBJECT宏报错的问题
在Qt中继承QObject,并且加上Q_OBJECT宏,有时候会报错,比如我的错误: error: debug/httpmgr.o:httpmgr.cpp:(.rdata$.refptr._ZTV7HttpMgr[.refptr._ZTV7HttpMgr]0x0): undefined reference to vtable for HttpMgr 意思是没有虚…...