git reset HEAD filename 有什么作用?
what does git reset HEAD filename do?
我在分支 B 上,我正在尝试将分支 A 合并到分支 B,但我想合并除一个文件之外的所有更改。经过一番搜索,我找到了这个解决方案:
git merge --no-commit <merge-branch>
git reset HEAD myfile.txt
git checkout -- myfile.txt
git commit -m "merged <merge-branch>"
我对第二行感到很困惑:git reset HEAD myfile.txt
;这条线有什么作用?它对合并除一个文件以外的所有文件的目标有何帮助?
它将它重置为当前分支的头部 (HEAD)。
您有一个文件希望不受合并影响。但该文件实际上可能会受到合并的影响。因此,您执行了合并,但没有声明完成就停止了。
git merge --no-commit <merge-branch>
现在撤消合并对该文件的影响(如果有的话)。
git reset HEAD myfile.txt
git checkout -- myfile.txt
现在您声明合并完成。
git commit -m "merged <merge-branch>"
使用 git reset
时要记住的是 git
跟踪两组文件:
- 您的"working tree",您直接编辑的检出文件。
- "index" 或 "staging area" 将在您下次 运行
git commit
时提交的文件,您通常使用 git add
和git rm
.
它还会跟踪您当前签出的提交以及哪个分支。
git reset
有多种模式和参数,which you can look up in the documentation.
当使用一个或多个路径以及分支或提交引用(任何 "tree-ish",如 git
手册所述)指定时,git reset
设置这些文件 在索引/暂存区到他们在提交时的状态,但不触及工作副本或分支指针。
最后,HEAD
指的是您当前签出的任何提交。
所以在这种情况下 git reset HEAD myfile.txt
将索引更改为 "when I next commit, please make the content of myfile.txt
the same as in the currently checked out commit"。换句话说,您不想提交对该文件的任何更改。
下一行 (git checkout -- myfile.txt
) 对 工作树 做同样的事情。如果您 运行 和 git status
之间,您会看到对 myfile.txt
的所有更改都列为 "unstaged".
and 都是正确的(我已经赞成它们)但是除非你已经阅读了 Git 的索引/staging-area 的功能,其中的一些部分有些晦涩难懂。事实上,如果不深入了解索引的一些细节,就无法正确解释合并的过程——而 git reset
的主要工作是操纵索引。所以: 是 索引,为什么它有三个名字?首先,简要了解一下 commits.
很有用
Git 提交是每个源文件的冻结快照,加上一些元数据
当您进行 Git 提交时,您真正做的是永久冻结 所有 文件的副本(好吧,所有你提交的文件,但这是一种同义反复)。该提交还存储了您的姓名和电子邮件地址,以及一个 date-and-time 标记——实际上,每个标记 两个 ——以及我们将在这里忽略的其他一些有用的东西,为了专注于每个文件的这些冻结副本。
显然,如果 Git 每次都为每个文件创建一个新副本,您的 Git 存储库会很快变得很大。所以 Git 不会那样做。每个冻结文件首先被压缩,变成read-only、Git-only形式。以这种方式存储的数据永远不会改变,事实上不能改变。它只是存储在一个大数据库中(Git 的 object 数据库,我们在这里可以忽略它)。这意味着一旦它们被提交,您的文件将一直以这种形式保存,如果您需要它们,这很好。但是,如果文件的冻结、压缩、read-only、Git-only 数据与(或任何)早期提交中的 相同,这也意味着Git 可以 re-use 之前保存的文件,而不是保存新的副本。由于大多数提交大多不会更改大多数文件,因此这很容易节省大量 space.
Frozen 对于完成任务来说很好,但对于完成工作毫无用处
这种冻结的 read-only、Git-only、压缩形式(我喜欢称之为 freeze-dried)有一些缺点。 freeze-dried 文件保存 space 并且可以被许多提交使用,但它们 仅 作为存档有用。它们必须扩展——再水化——成为一种有用的形式,以便你对它们进行任何工作,或者改变它们。
因此,Git也为您提供了一个工作区,Git调用work-tree或工作区tree 或 working tree 或该名称的某些变体。 Git 可以到此为止,freeze-dried Git-only 提交的文件和 work-tree 有用的文件。其他版本控制系统做到此为止。但是 Git 没有。 Git 继续为上次提交 out 后的每个 freeze-dried 文件保留一个副本——实际上是一个引用。因此,不是每个文件的 两个 副本——HEAD
提交中的冻结副本,以及 work-tree 中的工作文件——Git 具有 三个份每个文件。第三个副本位于 HEAD
副本和 work-tree 副本之间,是索引(主要)的内容。
索引有几个作用
索引,Git 也称为 暂存区——在很多方面这是一个更好的名字,但它遗漏了一些极端情况——保存了一份每个将进入 next 提交的文件。此副本采用 freeze-dried 格式,即已准备好进入新提交。这里的一个技巧是,展开冻结文件的过程比 re-freezing work-tree 文件的过程更快。因此,当您第一次 git checkout
一些提交时,Git 会用该提交的 来自 的每个文件填充索引,因为它出现在该提交中。这意味着他们也都准备好进入 next 提交。 Git 然后将这些冻结的副本再水化到 work-tree 中,这样您就可以看到并处理它们 on/with。
编辑 work-tree 副本后,git add
获取 work-tree 副本和 re-freeze-dries 副本,并将该版本填充到索引中(间接但不会'在这里真的很重要)。所以现在索引已更新——更新后的文件 staged 被复制到索引中,替换旧版本。同样,索引已为下一次提交做好准备。 Git 将 自动 re-use 所有未更改的 freeze-dried 文件!它真的很聪明,除非索引妨碍了你——例如,有时在合并过程中会发生这种情况。
上面的描述有点谎言。有关详细信息,请参阅 Checkout another branch when there are uncommitted changes on the current branch。但它是考虑 Git 的合理起始模型。这也导致了索引的第三个名称:Git 有时称它为 cache,因为它缓存了有关您的 work-tree 的信息。不过,这两个通用名称仍然是 staging area——这是有道理的,因为 git add
copi把东西放进去,然后它就像一个舞台场景,你可以通过提交来拍照和存档——index.
当您 运行 git merge
时,该索引的作用将大大扩展。当您有合并冲突时,您只会看到。如果您没有任何合并冲突,git merge
会扩展索引,完成所有工作,然后将其折叠起来。为了避免这个答案变得更长,让我们假设情况确实如此。 :-) 在那种特殊情况下——一切顺利——索引现在包含每个 merged 文件,除了 freeze-dried 之外——匹配合并的 work-tree 也复制,就好像您(或 Git)对所有合并文件都有 运行 git add
。
通常,如果 git merge
能够像这样独立完成所有事情,git merge
会继续进行 合并提交 。合并提交几乎与常规 (non-merge) 提交完全相同——它像往常一样有一个快照,像往常一样从索引中创建。唯一真正的区别是在它的元数据中,合并提交记录 both 当前 HEAD
提交 and 另一个提交作为它的 (二)parent秒。普通提交只记录当前提交作为他们的(一个)parent.
由于您使用了 --no-commit
,git merge
在 进行此合并提交之前停止了 ,但保留设置以便 git commit
或 git merge --continue
将进行合并提交。 此时,请记住,索引包含所有合并的文件。这就是 git reset
的用武之地。
git reset
git reset
所做的是......好吧,它可能真的很复杂,因为 git reset
,就像许多其他 Git 命令一样,将太多不同的东西塞进一个 user-facing命令。但是 在这种情况下 ,git reset
所做的是 git add
的一种对应。让我们绘制 HEAD -- index -- work-tree 设置如下:
HEAD index work-tree
--------- --------- ---------
README.md README.md README.md
Makefile Makefile Makefile
myfile.txt myfile.txt myfile.txt
... ... ...
这些不同文件的每个副本的内容可能不同。也就是说,HEAD:README.md
将永远冻结在当前提交的 README.md
中。它采用 freeze-dried 格式,并且 无法更改 。 README.md
的索引副本——例如,你可以用 git show :README.md
查看——也是 freeze-dried 格式,但 你可以随时更改它。 当然,普通 READMD.md
文件是您 work-tree 中的普通普通文件,您可以用它做任何您想做的事情。
git reset HEAD myfile.txt
所做的是告诉 Git:将 freeze-dried HEAD:myfile.txt
复制到索引 :myfile.txt
. 将此与 git add myfile.txt
进行比较,它告诉 Git: 复制 work-tree,将 myfile.txt
重新水化为 :myfile.txt
,freeze-drying 它过程中.
git checkout
更新索引副本后,您可能想查看更新的内容。你可以使用 git show :myfile.txt
在你的屏幕上看到它(或者在 window 或其他什么)。但这就是 git checkout -- myfile.txt
的用武之地。
就像git reset
一样,git checkout
可以做的事情太多了(in Git 2.23 git checkout
is to be replaced with two separate Git commands, which each do fewer things)。 git checkout
的这种特殊形式告诉 Git: 将文件 myfile.txt
从索引(从 :myfile.txt
复制到 work-tree,再水化它过程中。
你可以通过一个命令缩短整个事情,因为git checkout
可以将文件从commit复制到你的work-tree:
git checkout HEAD myfile.txt
会完成这项工作。这种git checkout
先把HEAD:myfile.txt
拷贝到:myfile.txt
——在这个操作中保持freeze-dried格式——然后把索引拷贝拷贝到work-tree拷贝.
总结
索引或临时区域位于当前提交和work-tree之间。当您在 Git 存储库上工作时,使用 work-tree 中的文件,Git 并不关心您对 work-tree 做了什么。 Git 关心你对 index 做什么,因为 Git 让你的 next 提交——无论是普通的使用一个 parent 提交,或使用两个合并 - 从您当时在索引中拥有的任何内容 运行 git commit
.
索引的存在使您能够更改将进入下一次提交的内容。这包括您使用 --no-commit
故意停止的合并的情况。 (索引也是使任何给定文件 tracked 或 untracked 的原因,并且 - 因为它在合并期间扮演扩展角色 - 处理未合并 文件,其中 Git 无法自行合并。有时试图忽略索引很诱人,因为您无法 查看 它直接(好吧,你可以用 git show
一点点,用 git ls-files --stage
更多)。但它在 Git 的大部分内容中起着巨大而核心的作用忽略它是不明智的操作。
我在分支 B 上,我正在尝试将分支 A 合并到分支 B,但我想合并除一个文件之外的所有更改。经过一番搜索,我找到了这个解决方案:
git merge --no-commit <merge-branch>
git reset HEAD myfile.txt
git checkout -- myfile.txt
git commit -m "merged <merge-branch>"
我对第二行感到很困惑:git reset HEAD myfile.txt
;这条线有什么作用?它对合并除一个文件以外的所有文件的目标有何帮助?
它将它重置为当前分支的头部 (HEAD)。
您有一个文件希望不受合并影响。但该文件实际上可能会受到合并的影响。因此,您执行了合并,但没有声明完成就停止了。
git merge --no-commit <merge-branch>
现在撤消合并对该文件的影响(如果有的话)。
git reset HEAD myfile.txt
git checkout -- myfile.txt
现在您声明合并完成。
git commit -m "merged <merge-branch>"
使用 git reset
时要记住的是 git
跟踪两组文件:
- 您的"working tree",您直接编辑的检出文件。
- "index" 或 "staging area" 将在您下次 运行
git commit
时提交的文件,您通常使用git add
和git rm
.
它还会跟踪您当前签出的提交以及哪个分支。
git reset
有多种模式和参数,which you can look up in the documentation.
当使用一个或多个路径以及分支或提交引用(任何 "tree-ish",如 git
手册所述)指定时,git reset
设置这些文件 在索引/暂存区到他们在提交时的状态,但不触及工作副本或分支指针。
最后,HEAD
指的是您当前签出的任何提交。
所以在这种情况下 git reset HEAD myfile.txt
将索引更改为 "when I next commit, please make the content of myfile.txt
the same as in the currently checked out commit"。换句话说,您不想提交对该文件的任何更改。
下一行 (git checkout -- myfile.txt
) 对 工作树 做同样的事情。如果您 运行 和 git status
之间,您会看到对 myfile.txt
的所有更改都列为 "unstaged".
git reset
的主要工作是操纵索引。所以: 是 索引,为什么它有三个名字?首先,简要了解一下 commits.
Git 提交是每个源文件的冻结快照,加上一些元数据
当您进行 Git 提交时,您真正做的是永久冻结 所有 文件的副本(好吧,所有你提交的文件,但这是一种同义反复)。该提交还存储了您的姓名和电子邮件地址,以及一个 date-and-time 标记——实际上,每个标记 两个 ——以及我们将在这里忽略的其他一些有用的东西,为了专注于每个文件的这些冻结副本。
显然,如果 Git 每次都为每个文件创建一个新副本,您的 Git 存储库会很快变得很大。所以 Git 不会那样做。每个冻结文件首先被压缩,变成read-only、Git-only形式。以这种方式存储的数据永远不会改变,事实上不能改变。它只是存储在一个大数据库中(Git 的 object 数据库,我们在这里可以忽略它)。这意味着一旦它们被提交,您的文件将一直以这种形式保存,如果您需要它们,这很好。但是,如果文件的冻结、压缩、read-only、Git-only 数据与(或任何)早期提交中的 相同,这也意味着Git 可以 re-use 之前保存的文件,而不是保存新的副本。由于大多数提交大多不会更改大多数文件,因此这很容易节省大量 space.
Frozen 对于完成任务来说很好,但对于完成工作毫无用处
这种冻结的 read-only、Git-only、压缩形式(我喜欢称之为 freeze-dried)有一些缺点。 freeze-dried 文件保存 space 并且可以被许多提交使用,但它们 仅 作为存档有用。它们必须扩展——再水化——成为一种有用的形式,以便你对它们进行任何工作,或者改变它们。
因此,Git也为您提供了一个工作区,Git调用work-tree或工作区tree 或 working tree 或该名称的某些变体。 Git 可以到此为止,freeze-dried Git-only 提交的文件和 work-tree 有用的文件。其他版本控制系统做到此为止。但是 Git 没有。 Git 继续为上次提交 out 后的每个 freeze-dried 文件保留一个副本——实际上是一个引用。因此,不是每个文件的 两个 副本——HEAD
提交中的冻结副本,以及 work-tree 中的工作文件——Git 具有 三个份每个文件。第三个副本位于 HEAD
副本和 work-tree 副本之间,是索引(主要)的内容。
索引有几个作用
索引,Git 也称为 暂存区——在很多方面这是一个更好的名字,但它遗漏了一些极端情况——保存了一份每个将进入 next 提交的文件。此副本采用 freeze-dried 格式,即已准备好进入新提交。这里的一个技巧是,展开冻结文件的过程比 re-freezing work-tree 文件的过程更快。因此,当您第一次 git checkout
一些提交时,Git 会用该提交的 来自 的每个文件填充索引,因为它出现在该提交中。这意味着他们也都准备好进入 next 提交。 Git 然后将这些冻结的副本再水化到 work-tree 中,这样您就可以看到并处理它们 on/with。
编辑 work-tree 副本后,git add
获取 work-tree 副本和 re-freeze-dries 副本,并将该版本填充到索引中(间接但不会'在这里真的很重要)。所以现在索引已更新——更新后的文件 staged 被复制到索引中,替换旧版本。同样,索引已为下一次提交做好准备。 Git 将 自动 re-use 所有未更改的 freeze-dried 文件!它真的很聪明,除非索引妨碍了你——例如,有时在合并过程中会发生这种情况。
上面的描述有点谎言。有关详细信息,请参阅 Checkout another branch when there are uncommitted changes on the current branch。但它是考虑 Git 的合理起始模型。这也导致了索引的第三个名称:Git 有时称它为 cache,因为它缓存了有关您的 work-tree 的信息。不过,这两个通用名称仍然是 staging area——这是有道理的,因为 git add
copi把东西放进去,然后它就像一个舞台场景,你可以通过提交来拍照和存档——index.
当您 运行 git merge
时,该索引的作用将大大扩展。当您有合并冲突时,您只会看到。如果您没有任何合并冲突,git merge
会扩展索引,完成所有工作,然后将其折叠起来。为了避免这个答案变得更长,让我们假设情况确实如此。 :-) 在那种特殊情况下——一切顺利——索引现在包含每个 merged 文件,除了 freeze-dried 之外——匹配合并的 work-tree 也复制,就好像您(或 Git)对所有合并文件都有 运行 git add
。
通常,如果 git merge
能够像这样独立完成所有事情,git merge
会继续进行 合并提交 。合并提交几乎与常规 (non-merge) 提交完全相同——它像往常一样有一个快照,像往常一样从索引中创建。唯一真正的区别是在它的元数据中,合并提交记录 both 当前 HEAD
提交 and 另一个提交作为它的 (二)parent秒。普通提交只记录当前提交作为他们的(一个)parent.
由于您使用了 --no-commit
,git merge
在 进行此合并提交之前停止了 ,但保留设置以便 git commit
或 git merge --continue
将进行合并提交。 此时,请记住,索引包含所有合并的文件。这就是 git reset
的用武之地。
git reset
git reset
所做的是......好吧,它可能真的很复杂,因为 git reset
,就像许多其他 Git 命令一样,将太多不同的东西塞进一个 user-facing命令。但是 在这种情况下 ,git reset
所做的是 git add
的一种对应。让我们绘制 HEAD -- index -- work-tree 设置如下:
HEAD index work-tree
--------- --------- ---------
README.md README.md README.md
Makefile Makefile Makefile
myfile.txt myfile.txt myfile.txt
... ... ...
这些不同文件的每个副本的内容可能不同。也就是说,HEAD:README.md
将永远冻结在当前提交的 README.md
中。它采用 freeze-dried 格式,并且 无法更改 。 README.md
的索引副本——例如,你可以用 git show :README.md
查看——也是 freeze-dried 格式,但 你可以随时更改它。 当然,普通 READMD.md
文件是您 work-tree 中的普通普通文件,您可以用它做任何您想做的事情。
git reset HEAD myfile.txt
所做的是告诉 Git:将 freeze-dried HEAD:myfile.txt
复制到索引 :myfile.txt
. 将此与 git add myfile.txt
进行比较,它告诉 Git: 复制 work-tree,将 myfile.txt
重新水化为 :myfile.txt
,freeze-drying 它过程中.
git checkout
更新索引副本后,您可能想查看更新的内容。你可以使用 git show :myfile.txt
在你的屏幕上看到它(或者在 window 或其他什么)。但这就是 git checkout -- myfile.txt
的用武之地。
就像git reset
一样,git checkout
可以做的事情太多了(in Git 2.23 git checkout
is to be replaced with two separate Git commands, which each do fewer things)。 git checkout
的这种特殊形式告诉 Git: 将文件 myfile.txt
从索引(从 :myfile.txt
复制到 work-tree,再水化它过程中。
你可以通过一个命令缩短整个事情,因为git checkout
可以将文件从commit复制到你的work-tree:
git checkout HEAD myfile.txt
会完成这项工作。这种git checkout
先把HEAD:myfile.txt
拷贝到:myfile.txt
——在这个操作中保持freeze-dried格式——然后把索引拷贝拷贝到work-tree拷贝.
总结
索引或临时区域位于当前提交和work-tree之间。当您在 Git 存储库上工作时,使用 work-tree 中的文件,Git 并不关心您对 work-tree 做了什么。 Git 关心你对 index 做什么,因为 Git 让你的 next 提交——无论是普通的使用一个 parent 提交,或使用两个合并 - 从您当时在索引中拥有的任何内容 运行 git commit
.
索引的存在使您能够更改将进入下一次提交的内容。这包括您使用 --no-commit
故意停止的合并的情况。 (索引也是使任何给定文件 tracked 或 untracked 的原因,并且 - 因为它在合并期间扮演扩展角色 - 处理未合并 文件,其中 Git 无法自行合并。有时试图忽略索引很诱人,因为您无法 查看 它直接(好吧,你可以用 git show
一点点,用 git ls-files --stage
更多)。但它在 Git 的大部分内容中起着巨大而核心的作用忽略它是不明智的操作。