吉特
第2版

2.2 Git基础知识-记录对存储库的更改

将更改记录到存储库

此时,您应该有一个真诚地本地计算机上的Git存储库,以及签出或工作副本在你面前的所有文件中。通常,每次项目达到要记录的状态时,您都会希望开始进行更改并将这些更改的快照提交到存储库中。

请记住,工作目录中的每个文件可以处于以下两种状态之一:跟踪未追踪的.被跟踪的文件是上一个快照中的文件,以及任何新暂存的文件;它们可以是未修改、修改或暂存的。简而言之,被跟踪的文件是Git知道的文件。

未跟踪的文件就是一切 — 工作目录中不在上次快照中且不在临时区域中的任何文件。当你第一次克隆存储库时,你的所有文件都会被跟踪和修改,因为Git刚刚将它们签出,而你没有编辑任何内容。

当您编辑文件时,Git会将其视为已修改,因为您自上次提交以来已经对其进行了更改。在工作时,您可以有选择地暂存这些修改过的文件,然后提交所有这些暂存的更改,然后循环重复。

文件状态的生命周期
图8。文件状态的生命周期

检查文件的状态

用于确定哪些文件处于何种状态的主要工具是git状态命令。如果您在克隆后直接运行此命令,您应该会看到以下内容:

$git状态在分支主机上您的分行是最新的“origin/master”。无需提交,工作树已清理

这意味着您有一个干净的工作目录;换句话说,没有修改任何跟踪的文件。Git也看不到任何未跟踪的文件,否则会在此处列出。最后,该命令告诉您在哪个分支上,并通知您它没有偏离服务器上的同一分支。目前,该分支始终主人,这是默认值;你在这里不用担心。Git分支将详细介绍分支和参考。

注释

GitHub将默认分支名称从更改为主人主要的在2020年年中,其他Git主持人也纷纷效仿。因此,您可能会发现一些新创建的存储库中的默认分支名称是主要的而不是主人.此外,可以更改默认分支名称(如中所示您的默认分支机构名称),因此您可能会看到默认分支的不同名称。

然而,Git本身仍然使用主人作为默认设置,因此我们将在整本书中使用它。

假设您在项目中添加了一个新文件自述文件文件。如果文件以前不存在,则运行git状态,您看到的未跟踪文件如下所示:

$echo“我的项目”>自述$git状态在分支主机上您的分行是最新的“origin/master”。未跟踪的文件:(使用“git add<file>…”将要提交的内容包括在内)自述文件没有添加任何内容以提交,但存在未跟踪的文件(使用“git add”进行跟踪)

你可以看到你的新自述文件文件是未跟踪的,因为它位于状态输出中的“未跟踪的文件”标题下。Untracked基本上意味着Git会看到一个文件,您在上一个快照(提交)中没有该文件,并且该文件尚未转移;Git不会在您的提交快照中包含它,除非您明确要求它这样做。这样做是为了避免意外地开始包含生成的二进制文件或其他您不想包含的文件。你确实想开始包括自述文件,让我们开始跟踪文件。

跟踪新文件

为了开始跟踪新文件,可以使用以下命令git添加.要开始跟踪自述文件文件,您可以运行以下命令:

$git添加自述文件

如果再次运行状态命令,您可以看到自述文件现在已跟踪并暂存文件以提交:

$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git restore--staged<file>…”取消stage)新文件:README

您可以看出,它是分阶段的,因为它位于“要提交的更改”标题下。如果此时提交,则为运行时的文件版本git添加是后续历史快照中的内容。你可能还记得,当你跑步时初始化早些时候,你跑了git添加<文件> — 那就是开始跟踪目录中的文件。这个git添加命令获取文件或目录的路径名;如果是一个目录,该命令会递归地添加该目录中的所有文件。

暂存修改的文件

让我们更改已跟踪的文件。如果您更改了以前跟踪的名为贡献.md然后运行您的git状态再次执行命令,您将得到如下内容:

$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)新文件:README未暂存以提交的更改:(使用“git add<file>…”更新要提交的内容)(使用“git checkout-->file>…”放弃工作目录中的更改)修改:CONTRIBUTING.md

这个贡献.md文件出现在名为“未暂存以提交的更改”的部分下 — 这意味着已在工作目录中修改了被跟踪的文件,但尚未暂存。要准备它,您可以运行git添加命令。git添加是一个多用途司令部 — 您可以使用它来开始跟踪新文件、暂存文件,以及执行其他操作,如将合并冲突文件标记为已解决。将其视为“将此内容精确地添加到下一次提交中”,而不是“将此文件添加到项目中”,这可能会有所帮助。我们跑吧git添加现在开始贡献.md文件,然后运行git状态再一次:

$git add贡献.md$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)新文件:README修改:CONTRIBUTING.md

这两个文件都已暂存,并将进入您的下一次提交。在这一点上,假设你记得你想做的一点改变贡献.md在你承诺之前。您再次打开它并进行更改,就可以提交了。然而,让我们跑吧git状态再来一次:

$vim贡献.md$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)新文件:README修改:CONTRIBUTING.md未暂存以提交的更改:(使用“git add<file>…”更新要提交的内容)(使用“git checkout-->file>…”放弃工作目录中的更改)修改:CONTRIBUTING.md

搞什么鬼?现在贡献.md列为两个阶段未老化。这怎么可能?事实证明,Git在运行git添加命令。如果您现在提交贡献.md就像你上次跑数字加法命令是它进入提交的方式,而不是运行时在工作目录中显示的文件版本git提交.如果在运行后修改文件git添加,你必须跑数字加法再次暂存文件的最新版本:

$git add贡献.md$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)新文件:README修改:CONTRIBUTING.md

短期状态

git状态输出相当全面,也相当冗长。Git还有一个简短的状态标志,这样您可以更紧凑地查看更改。如果你跑步git状态-sgit状态--短您可以从以下命令获得更简单的输出:

$git状态-sM自述MM Rakefile文件A库/git.rbM库/simplegit.rb?? 许可证.txt

未跟踪的新文件具有??在它们旁边,添加到临时区域的新文件有一个A类,修改的文件具有M(M)等等。输出有两列 — 左边的列指示暂存区域的状态,右边的列指示工作树的状态。例如,在输出中自述文件文件在工作目录中被修改,但尚未暂存,而库/simplegit.rb文件被修改和暂存。这个Rakefile文件已修改、暂存,然后再次修改,因此对其进行了暂存和未暂存的更改。

忽略文件

通常,你会有一类文件,你不希望Git自动添加,甚至显示你没有被跟踪。这些文件通常是自动生成的文件,例如日志文件或生成系统生成的文件。在这种情况下,您可以创建一个文件,列出与之匹配的模式,命名为.gitignore(.git忽略).下面是一个示例.gitignore(.git忽略)文件:

$cat.gitignore*.[办公自动化]*~

第一行告诉Git忽略任何以“.o”或“.a”结尾的文件 — 对象和存档文件,这些文件可能是构建代码的产物。第二行告诉Git忽略名称以波浪号结尾的所有文件(~),Emacs等许多文本编辑器都使用它来标记临时文件。您还可以包括日志、tmp或pid目录;自动生成的文档;等等。设置.gitignore(.git忽略)通常,在开始之前为新存储库创建一个文件是一个好主意,这样您就不会意外地在Git存储库中提交您真正不想要的文件。

您可以在.gitignore(.git忽略)文件如下:

  • 空行或以开头的行#被忽略。

  • 标准全局模式有效,并将在整个工作树中递归应用。

  • 你可以用正斜杠开始图案(/)以避免递归。

  • 可以用正斜杠结束图案(/)以指定目录。

  • 你可以用感叹号开始否定一个模式(!).

Glob模式类似于shell使用的简化正则表达式。星号(*)匹配零个或多个字符;[美国广播公司]匹配括号内的任何字符(在本例中为a、b或c);问号(?)匹配单个字符;和括号,用连字符分隔字符([0-9])匹配它们之间的任何字符(在本例中为0到9)。您还可以使用两个星号来匹配嵌套目录;a/**/z将匹配自动/自动,a/b/z型,a/b/c/z等等。

这里是另一个例子.gitignore(.git忽略)文件:

#忽略所有.a文件*.a个#但要跟踪lib.a,即使您忽略了上面的.a文件!图书馆.a#只忽略当前目录中的TODO文件,不忽略subdir/TODO/TODO公司#忽略名为build的任何目录中的所有文件建造/#忽略doc/notes.txt,但不忽略doc/server/arch.txt文档/*.txt#忽略doc/目录及其任何子目录中的所有.pdf文件文档/**/*.pdf
提示

GitHub维护了一个相当全面的良好列表.gitignore(.git忽略)许多项目和语言的文件示例https://github.com/github/gitignore如果你想要一个项目的起点。

注释

在简单的情况下,存储库可能只有一个.gitignore(.git忽略)文件,它递归地应用于整个存储库。然而,也可以有额外的.gitignore(.git忽略)子目录中的文件。这些嵌套中的规则.gitignore(.git忽略)文件仅适用于它们所在目录下的文件。Linux内核源代码库有206个.gitignore(.git忽略)文件夹。

深入了解多重.gitignore(.git忽略)文件;看见男子吉特忽略了解详细信息。

查看您的暂存和未暂存更改

如果git状态命令对你来说太模糊了————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————你想知道你到底更改了什么,而不仅仅是更改了哪些文件 — 您可以使用差异比较命令。我们会掩护差异比较稍后会更详细地介绍,但您可能最常使用它来回答这两个问题:您已经更改了哪些内容,但尚未上演?你准备表演什么?尽管git状态通常通过列出文件名来回答这些问题,差异比较显示添加和删除的精确行 — 可以说是补丁。

假设您编辑并准备自述文件然后编辑贡献.md文件而不暂存。如果您运行git状态命令,您再次看到如下内容:

$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)修改:README未暂存以供提交的更改:(使用“git add<file>…”更新要提交的内容)(使用“git checkout-->file>…”放弃工作目录中的更改)修改:CONTRIBUTING.md

要查看您已更改但尚未暂存的内容,请键入差异比较没有其他参数:

$git差异diff—git a/CONTRIBUTING.md b/CONTRIBUING.md指数8ebb991..643e24f 100644---a/贡献.md+++b/贡献.md@@-65,7+65,8@@直接分支,事情可能会变得一团糟。请在提交PR时详细描述您的更改;如果我们必须阅读整个差异来找出你为什么要贡献首先,你不太可能得到反馈和改变-在中合并。+合并到中。此外,如果您的补丁+超过十几行。如果你开始在某个特定领域工作,请随时提交PR这突出了你正在进行的工作(并在公关标题中注明

该命令将工作目录中的内容与临时区域中的内容进行比较。结果告诉你你所做的改变,你还没有上演。

如果您想查看下一次提交中要转移的内容,可以使用git diff—分段.此命令将您的暂存更改与上次提交进行比较:

$git diff--暂存diff—git a/README b/README新文件模式100644索引0000000..03902a1---/dev/null+++b/自述@@ -0,0 +1 @@+我的项目

值得注意的是差异比较它本身不会显示自上次提交以来所做的所有更改————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————只有尚未稳定的更改。如果你已经准备好了所有的更改,差异比较不会给你任何输出。

再举一个例子,如果您准备贡献.md然后编辑它,您可以使用差异比较查看暂存文件中的更改和未暂存的更改。如果我们的环境看起来像这样:

$git添加贡献.md$echo“#测试线”>>贡献.md$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)修改:CONTRIBUTING.md未暂存以提交的更改:(使用“git add<file>…”更新要提交的内容)(使用“git checkout-->file>…”放弃工作目录中的更改)修改:CONTRIBUTING.md

现在您可以使用差异比较查看哪些内容仍未稳定:

$git差异diff—git a/CONTRIBUTING.md b/CONTRIBUING.md索引643e24f。。87f08c8 100644号---a/贡献.md+++b/贡献.md@@-119.3+119.4@@##初级项目查看我们的[项目列表](https://github.com/libgit2/libgit0/blob/development/PROJECTS.md).+#测试线

git diff—缓存看看你到目前为止上演了什么(--分阶段的--缓存的同义词):

$git diff--缓存diff—git a/CONTRIBUTING.md b/CONTRIBUING.md指数8ebb991..643e24f 100644---a/贡献.md+++b/贡献.md@@-65,7+65,8@@直接分支,事情可能会变得一团糟。当你提交你的PR时,请包括一个很好的描述你的变化;如果我们必须阅读整个差异来找出你为什么要贡献首先,你不太可能得到反馈和改变-在中合并。+合并到中。此外,如果您的补丁+超过十几行。如果你开始在某个特定领域工作,请随时提交PR这突出了你正在进行的工作(并在公关标题中注明
注释
外部工具中的Git Diff

我们将继续使用差异比较在书的其余部分以各种方式进行指挥。如果您更喜欢图形或外部差异查看程序,那么还有另一种方法可以查看这些差异。如果你跑步git差异工具而不是差异比较,您可以在emerge、vimdiff等软件(包括商业产品)中查看这些差异。运行git difftool--工具帮助查看您的系统上有什么可用的。

提交您的更改

现在,您的临时区域已按您希望的方式设置好,您可以提交更改。记住,任何尚未稳定的东西 — 已创建或修改但尚未运行的任何文件git添加自从你编辑了他们 — 不会参与这个承诺。它们将作为修改后的文件保存在磁盘上。在这种情况下,假设您上次跑步git状态,您看到所有内容都已暂存,因此您已准备好提交更改。提交的最简单方法是键入git提交:

$git提交

这样会启动您选择的编辑器。

注释

这是由你的贝壳设置的编辑环境变量 — 通常是vim或emacs,尽管您可以使用git config—全局核心编辑器您在中看到的命令入门.

编辑器显示以下文本(本例为Vim屏幕):

#请输入更改的提交消息。线条开始#带有“#”的将被忽略,并且一条空消息将中止提交。#在分支主机上#您的分行是最新的“origin/master”。##要提交的更改:#新文件:README#修改:CONTRIBUTING.md#~~~“.git/COMMIT_EDITMSG”9L,283C

您可以看到,默认提交消息包含git状态命令被注释掉,顶部有一行空白。您可以删除这些注释并键入提交消息,也可以将它们留在那里以帮助您记住要提交的内容。

注释

要更明确地提醒您修改了什么,您可以通过-v(v)选择git提交.这样做还可以将更改的差异放在编辑器中,以便您可以确切地看到要提交的更改。

当您退出编辑器时,Git会使用该提交消息创建您的提交(去掉注释和差异)。

或者,您可以使用内联的犯罪命令,方法是在-米标志,如下所示:

$git commit-m“故事182:修复速度基准”[master 463dc4f]故事182:确定速度基准2个文件已更改,2个插入(+)创建模式100644自述

现在您已经创建了第一次提交!您可以看到,提交为您提供了关于其自身的一些输出:您提交到哪个分支(主人),提交的SHA-1校验和是什么(463直流4f)、更改了多少文件,以及有关提交中添加和删除的行的统计信息。

请记住,提交会记录您在临时区域中设置的快照。你没有做的任何事情都会被修改;您可以再次提交以将其添加到历史记录中。每次执行提交时,都会记录项目的快照,以便稍后恢复或比较。

跳过暂存区域

尽管它对于按照您想要的方式创建提交非常有用,但分段区域有时比您在工作流中需要的要复杂一些。如果您想跳过暂存区域,Git提供了一个简单的快捷方式。添加-一个选项git提交命令使Git在执行提交之前自动暂存已跟踪的每个文件,使您可以跳过git添加部分:

$git状态在分支主机上您的分行是最新的“origin/master”。未暂存以提交的更改:(使用“git add<file>…”更新要提交的内容)(使用“git checkout-->file>…”放弃工作目录中的更改)修改:CONTRIBUTING.md没有添加更改以提交(使用“git add”和/或“git commit-a”)$git commit-a-m“添加新基准测试”[master 83e38c7]添加新基准1个文件已更改,5次插入(+),0次删除(-)

注意你不必跑步git添加贡献.md在提交之前,请在本例中提交。那是因为-一个标志包括所有更改的文件。这很方便,但要小心;有时,此标志会导致您包含不需要的更改。

正在删除文件

要从Git中删除文件,您必须将其从跟踪的文件中删除(更准确地说,从暂存区域中删除),然后提交。这个移除文件命令可以做到这一点,并且还可以从工作目录中删除该文件,这样下次就不会将其视为未跟踪的文件。

如果您只是从工作目录中删除该文件,它会显示在“Changes not staged for commit”(未提交的更改)下(即,未老化)您的区域git状态输出:

$rm项目.md$git状态在分支主机上您的分行是最新的“origin/master”。未暂存以提交的更改:(使用“git-add/rm<file>…”更新将提交的内容)(使用“git checkout-->file>…”放弃工作目录中的更改)已删除:PROJECTS.md没有添加更改以提交(使用“git add”和/或“git commit-a”)

那么,如果你跑步移除文件,它分阶段删除文件:

$git rm项目.mdrm“项目.md”$git状态在分支主机上您的分行是最新的“origin/master”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)已删除:PROJECTS.md

下次提交时,该文件将消失,不再被跟踪。如果修改了文件或已将其添加到临时区域,则必须使用-(f)选项。这是一项安全功能,用于防止意外删除尚未记录在快照中且无法从Git恢复的数据。

另一个有用的方法是将文件保留在工作树中,但将其从临时区域中删除。换句话说,你可能想把文件保存在硬盘上,但不再让Git跟踪它。如果您忘记向.gitignore(.git忽略)文件并意外地将其转储,如一个大日志文件或一堆.a个已编译的文件。为此,请使用--缓存的选项:

$git-rm—缓存的自述文件

您可以将文件、目录和文件全局模式传递给移除文件命令。这意味着您可以做以下事情:

$git rm日志/\*.log

注意反斜杠(\)在*.这是必要的,因为除了shell的文件扩展之外,Git还进行了自己的文件扩展。此命令删除所有具有.log文件中的扩展日志/目录。或者,您可以这样做:

亿美元rm\*~

此命令删除名称以~.

移动文件

与许多其他VCS不同,Git不显式跟踪文件移动。如果在Git中重命名文件,Git中不会存储元数据来告诉它您重命名了该文件。然而,Git在事后才弄清楚这一点是相当聪明的 — 稍后我们将处理检测文件移动的问题。

因此,Git有一个毫伏命令。如果要在Git中重命名文件,可以运行以下操作:

$git mv文件从文件到

而且效果很好。事实上,如果您运行这样的程序并查看状态,您会看到Git将其视为重命名的文件:

$git mv README.md自述$git状态在分支主机上您的分支机构是最新的“来源/主”。要提交的更改:(使用“git reset HEAD<file>…”取消stage)重命名:README.md->README

然而,这相当于运行这样的程序:

$mv README.md自述$git rm阅读.md$git添加自述文件

Git发现这是一个隐式重命名,所以您以这种方式重命名文件或使用毫伏命令。唯一真正的区别是重命名是一个命令而不是三个 — 这是一个方便的功能。更重要的是,您可以使用任何工具重命名文件,并解决添加/rm(毫米)稍后,在您提交之前。

滚动到顶部