Oli*_*n04 3 git parsing git-diff git-remote git-status
目前我正在获取最新的,然后运行git status
并解析输出,Your branch is up to date with 'origin/master'
但这感觉就像一个黑客。
我已经研究过使用,git status --porcelain
但这仅包括在系统上所做的文件更改,而不是在远程所做的更改。我不在乎实际进行了哪些更改,我只想知道是否存在任何更改(本地或远程)。
我将如何干净地实现这一目标?
要以编程方式获取当前分支与其上游分支上不同的提交计数,请使用git rev-list --count --left-right HEAD...@{upstream}
,或者git rev-list --count master...master@{upstream}
例如。注意,这里的三个点,其中独立分支名称或HEAD
从branch@{upstream}
该是如何git status
或git branch -vv
打印ahead 1
或behind 2
或up to date
或什么的。
请注意,这首先假设您在一个分支上,并且该分支有一个上游要领先和/或落后。如果上游是远程跟踪名称,例如origin/master
,则假定存储在远程跟踪名称中的值就是您想要存储在其中的值。
如果您正在编写这些内容的脚本,那么准确地了解(或定义)您所说的最新版本很重要。
纯粹在本地——即,在一个存储库 + 工作树组合中——需要考虑三个实体:
当前提交,又名HEAD
.
这可能是一个分离的 HEAD,其中HEAD
包含原始哈希 ID,或者相反,在分支上,其中HEAD
包含分支本身的名称。在分支上时,分支名称,例如master
,包含当前提交的原始哈希 ID。无论哪种方式,HEAD
始终指的是当前提交。1
当前提交本身是只读的(完全)和永久的(大多数情况下——你可以故意放弃提交,之后它们最终会被删除)。您可以更改哪个提交是当前提交(例如,),但您不能更改提交本身。由于提交无法更改,因此根据定义,它永远不会“过时”:它是任何东西。像任何提交一样,当前提交有一些元数据(谁做的,什么时候做的,等等)以及每个文件的完整快照。git checkout different-commit
存储在提交中的文件采用特殊的 Git-only 格式(当然是只读的)。
该工作树,这是简单的,你做你的工作。
在这里,您可以读取和写入每个文件。这些文件采用普通格式,未压缩且特定于 Git。你也可以在这里有 Git 不知道的文件,但在我们正确讨论这个之前,我们需要涵盖第三个实体。
该指数,也叫暂存区域或有时缓存。
该索引有多种用途(因此有多个名称),但我认为最好将其描述为您将进行的下一次提交,如果您现在进行提交。也就是说,索引(实际上只是一个文件)包含 Git 制作新快照、放入新提交所需的所有信息。因此,索引包含将进入您下一次提交的所有文件。
索引中的文件被压缩,并且是 Git-only 格式,就像提交中的文件一样。但是,对于我们这里的目的而言,关键的区别在于索引中的文件可以更改。您可以将新文件放入索引中,也可以从索引中删除现有文件。
所有这一切确实是一个文件复制从工作树,进入该指数。这将替换索引中的先前版本,以便索引现在与工作树匹配。或者,如果您希望删除文件,请从索引和工作树中删除该文件。git add file
git rm file
1级新的存储库具有完全没有提交,所以有一个例外:HEAD
可以指分支名称根本不存在。在一个全新的存储库中就是这种情况:HEAD
说当前分支是master
,但master
在您进行第一次提交之前实际上并不存在。
(这 git checkout --orphan
命令可以为另一个分支重新创建这种特殊的“在一个尚不存在的分支上”状态。这不是大多数人大多数时候会做的事情,但它可以出现在检查状态的程序中。)
git status
作用由于索引和工作树都是可写的,它们都可能是“脏的”或以某种方式导致某些东西“过时”。如果您认为工作树文件是最新的,它可能是过期的索引副本,因为它与工作树副本不匹配。一旦工作树文件被复制到索引中,索引就不再与HEAD
提交匹配,并且在某个时候需要一个新的提交。
git status
除了运行git rev-list --count --left-right
分支及其上游并获取这些数字之外,还有什么作用,2是它实际上运行了两个git diff
s(--name-status
因为它对详细补丁不感兴趣):
对比HEAD
指数。无论这里有什么不同,这些都是为 commit 暂存的更改,因为如果您现在进行提交,Git 将对整个索引进行快照,并且该快照将与当前提交的这些文件完全不同。
将索引与工作树进行比较。不管这里有什么不同,这些都是没有为 commit 暂存的更改。一旦你git add
在这些文件上运行,索引副本将匹配工作树副本,但不再匹配HEAD
副本,所以现在这些将是暂存以提交的更改。
2请注意,git status
首先检查您是否在某个分支上,如果是,则该分支是否具有上游设置。而且,这都是内置的,所以它不必运行单独的程序,但原理是一样的。
我们现在也可以正确定义文件未被跟踪的含义。一个未跟踪的文件很简单,就是一个不在索引中的文件。也就是说,如果我们从索引中删除(只)的文件用git rm --cached
,或者如果我们没有创建索引的相应文件中创建的工作树中的文件,我们有没有什么相同的工作树的文件名在索引中。这是一个未跟踪的文件。
如果文件是未经跟踪,git status
通常它抱怨道:在DIFF运行该指数比较了工作树说啊,这里是工作的树不在索引中的文件,和Git会告诉你,这未跟踪。如果它是故意未跟踪的,您可以git status
通过在文件中列出该文件或匹配它的路径名模式来关闭它.gitignore
。本质上,就在抱怨某个文件未被跟踪之前,Git 会查看 ignore 指令。3 但是,如果该文件是在索引中,Git的从不寻找它的任何名称.gitignore
。
3 ignore 指令还告诉git add
任何整体“添加所有内容”都应该避免添加该文件,如果它当前未被跟踪。
分支的上游可以是远程跟踪名称,例如origin/master
. 这些名称是您的 Git 记住其他一些 Git 分支的方式。要更新 remote 的远程跟踪名称origin
,您只需运行git fetch origin
.
请注意,您可以拥有多个遥控器!如果您fred
在第二个 URL 上添加第二个遥控器,git fetch fred
将调用该URL上的 Git ,并更新您的fred/master
等等。所以它运行很重要git fetch
的权遥控器。
git fetch
不带附加名称运行将获取当前分支上游的远程,或者从origin
当前分支没有上游,或者没有当前分支,所以这通常只是运行的问题git fetch
。
子模块实际上只是对另一个 Git 存储库的引用,但这给总体计划带来了全新的问题。每个 Git 存储库都有自己的HEAD
、工作树和索引。这些可以像以前一样干净或脏,并且如果子模块未处于 detached-HEAD 状态,则子模块的分支可以在其上游之前和/或之后。
然而,子模块存储库通常处于 detached-HEAD 状态。超级项目中的每个提交都列出了您的 Git 应该将子模块 Git 分离到的特定提交。当超级项目 Git 检出提交时,超级项目 Git 会将子模块的哈希 ID 存储到超级项目的索引中。这样每个新的超级项目提交都会记录正确的哈希 ID。
要更改哈希 ID,git add
在超级项目中将实际检出子模块的当前哈希 ID复制到超级项目存储库中的索引中(哇!)。所以如果你已经移动了子模块(通过git checkout
那里),你导航回超级项目,git add
在子模块路径上运行,现在超级项目的索引记录了正确的哈希 ID,为下一个超级项目提交做好准备。
(测试子模块是否在超级项目的索引所需的提交上比较困难。)
归档时间: |
|
查看次数: |
823 次 |
最近记录: |