用简单的英语来说,"git reset"是什么意思?做? [英] In plain English, what does "git reset" do?

查看:68
本文介绍了用简单的英语来说,"git reset"是什么意思?做?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过有趣的帖子解释关于git reset的微妙之处.

I have seen interesting posts explaining subtleties about git reset.

不幸的是,我对它的了解越多,我就越不了解它.我来自SVN背景,Git是一个全新的范例.我比较容易上手,但是Git更具技术性.

Unfortunately, the more I read about it, the more it appears that I don't understand it fully. I come from a SVN background and Git is a whole new paradigm. I got mercurial easily, but Git is much more technical.

我认为git reset接近hg revert,但似乎存在差异.

I think git reset is close to hg revert, but it seems there are differences.

那么git reset到底是做什么的?请提供有关以下内容的详细说明:

So what exactly does git reset do? Please include detailed explanations about:

  • 选项--hard--soft--merge;
  • 您使用HEAD使用的奇怪符号,例如HEAD^HEAD~1;
  • 具体的用例和工作流程;
  • 对工作副本,HEAD和您的整体压力水平的影响.
  • the options --hard, --soft and --merge;
  • the strange notation you use with HEAD such as HEAD^ and HEAD~1;
  • concrete use cases and work flows;
  • consequences on the working copy, the HEAD and your global stress level.

推荐答案

通常,git reset的功能是获取当前分支并将其重置为指向其他位置,并可能将索引和工作树带到一起.更具体地说,如果您的master分支(当前已签出)是这样的:

In general, git reset's function is to take the current branch and reset it to point somewhere else, and possibly bring the index and work tree along. More concretely, if your master branch (currently checked out) is like this:

- A - B - C (HEAD, master)

并且您意识到您希望母版指向B而不是C,您将使用git reset B将其移到那里:

and you realize you want master to point to B, not C, you will use git reset B to move it there:

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

离题:这与结帐不同.如果您运行git checkout B,则会得到以下信息:

Digression: This is different from a checkout. If you'd run git checkout B, you'd get this:

- A - B (HEAD) - C (master)

您最终处于分离的HEAD状态. HEAD,工作树,索引都与B匹配,但是master分支留在了C处.如果此时进行一次新提交D,则会得到此信息,这可能不是您想要的:

You've ended up in a detached HEAD state. HEAD, work tree, index all match B, but the master branch was left behind at C. If you make a new commit D at this point, you'll get this, which is probably not what you want:

- A - B - C (master)
       \
        D (HEAD)

请记住,reset不会提交提交,它只是更新一个分支(这是指向提交的指针)以指向另一个提交.剩下的只是您的索引和工作树发生了什么的详细信息.

Remember, reset doesn't make commits, it just updates a branch (which is a pointer to a commit) to point to a different commit. The rest is just details of what happens to your index and work tree.

我将在下一节对各种选项的描述中介绍git reset的许多主要用例.它确实可以用于各种各样的事情.共同的线程是所有这些都涉及重置分支,索引和/或工作树以指向/匹配给定的提交.

I cover many of the main use cases for git reset within my descriptions of the various options in the next section. It can really be used for a wide variety of things; the common thread is that all of them involve resetting the branch, index, and/or work tree to point to/match a given commit.

  • --hard可能会导致您真正失去工作.它会修改您的工作树.

  • --hard can cause you to really lose work. It modifies your work tree.

git reset [options] commit可能导致您(某种程度上)丢失提交.在上面的玩具示例中,我们丢失了提交C.它仍在存储库中,您可以通过查看git reflog show HEADgit reflog show master来找到它,但实际上不再可以从任何分支访问它.

git reset [options] commit can cause you to (sort of) lose commits. In the toy example above, we lost commit C. It's still in the repo, and you can find it by looking at git reflog show HEAD or git reflog show master, but it's not actually accessible from any branch anymore.

Git在30天后会永久删除此类提交,但在此之前,您可以通过再次将分支指向C来恢复C(git checkout C; git branch <new branch name>).

Git permanently deletes such commits after 30 days, but until then you can recover C by pointing a branch at it again (git checkout C; git branch <new branch name>).

改写手册页,最常见的用法是git reset [<commit>] [paths...]形式,这会将给定路径从给定提交重置为其状态.如果未提供路径,则将重置整个树,如果未提供提交,则将其视为HEAD(当前提交).这是git命令之间的常见模式(例如checkout,diff,log,尽管确切的语义有所不同),所以这并不奇怪.

Paraphrasing the man page, most common usage is of the form git reset [<commit>] [paths...], which will reset the given paths to their state from the given commit. If the paths aren't provided, the entire tree is reset, and if the commit isn't provided, it's taken to be HEAD (the current commit). This is a common pattern across git commands (e.g. checkout, diff, log, though the exact semantics vary), so it shouldn't be too surprising.

例如,git reset other-branch path/to/foo将path/to/foo中的所有内容重置为其他分支中的状态,git reset -- .将当前目录重置为HEAD中的状态,而简单的git reset将所有目录重置为其在HEAD中的状态.头.

For example, git reset other-branch path/to/foo resets everything in path/to/foo to its state in other-branch, git reset -- . resets the current directory to its state in HEAD, and a simple git reset resets everything to its state in HEAD.

有四个主要选项可以控制重置期间工作树和索引的变化.

There are four main options to control what happens to your work tree and index during the reset.

请记住,索引是git的临时区域"-您说git add准备提交时,事情就在这里.

Remember, the index is git's "staging area" - it's where things go when you say git add in preparation to commit.

  • --hard使所有内容都与您已重置的提交匹配.这可能是最容易理解的.您所有的本地更改都会受到破坏.一种主要用途是浪费您的工作,但不切换提交:git reset --hard表示git reset --hard HEAD,即,不更改分支,而摆脱所有本地更改.另一个只是将分支从一个位置移动到另一个位置,并使索引/工作树保持同步. 这是真正使您失去工作的人,因为它会修改您的工作树.非常非常确定要在运行任何reset --hard之前先丢弃本地工作.

  • --hard makes everything match the commit you've reset to. This is the easiest to understand, probably. All of your local changes get clobbered. One primary use is blowing away your work but not switching commits: git reset --hard means git reset --hard HEAD, i.e. don't change the branch but get rid of all local changes. The other is simply moving a branch from one place to another, and keeping index/work tree in sync. This is the one that can really make you lose work, because it modifies your work tree. Be very very sure you want to throw away local work before you run any reset --hard.

--mixed是默认设置,即git reset表示git reset --mixed.它重置索引,但不重置工作树.这意味着您的所有文件均完好无损,但是原始提交和您重置为的提交之间的任何差异都将显示为本地修改(或未跟踪的文件),并且具有git状态.当您意识到自己做了一些错误的提交,但又想保留所有已完成的工作,以便对其进行修复和重新提交时,请使用此功能.为了提交,您必须再次将文件添加到索引(git add ...).

--mixed is the default, i.e. git reset means git reset --mixed. It resets the index, but not the work tree. This means all your files are intact, but any differences between the original commit and the one you reset to will show up as local modifications (or untracked files) with git status. Use this when you realize you made some bad commits, but you want to keep all the work you've done so you can fix it up and recommit. In order to commit, you'll have to add files to the index again (git add ...).

--soft不会触摸索引工作树.您的所有文件都与--mixed一样完好无损,但所有更改都显示为changes to be committed且具有git状态(即已检查以准备提交).当您意识到自己做了一些错误的提交,但工作很顺利时,请使用此功能-您要做的就是以不同的方式重新提交它.索引未更改,因此您可以根据需要立即提交-所生成的提交将具有与重置之前相同的内容.

--soft doesn't touch the index or work tree. All your files are intact as with --mixed, but all the changes show up as changes to be committed with git status (i.e. checked in in preparation for committing). Use this when you realize you've made some bad commits, but the work's all good - all you need to do is recommit it differently. The index is untouched, so you can commit immediately if you want - the resulting commit will have all the same content as where you were before you reset.

--merge是最近添加的,旨在帮助您中止失败的合并.这是必要的,因为git merge实际上将允许您尝试与脏工作树(具有本地修改的工作树)进行合并,只要这些修改位于不受合并影响的文件中即可. git reset --merge重置索引(如--mixed-所有更改都显示为本地修改),并重置受合并影响的文件,但将其他文件保留下来.希望这将使一切恢复到错误合并之前的状态.通常将其用作git reset --merge(表示git reset --merge HEAD),因为您只想重置合并,而实际上不移动分支. (由于合并失败,HEAD尚未更新)

--merge was added recently, and is intended to help you abort a failed merge. This is necessary because git merge will actually let you attempt a merge with a dirty work tree (one with local modifications) as long as those modifications are in files unaffected by the merge. git reset --merge resets the index (like --mixed - all changes show up as local modifications), and resets the files affected by the merge, but leaves the others alone. This will hopefully restore everything to how it was before the bad merge. You'll usually use it as git reset --merge (meaning git reset --merge HEAD) because you only want to reset away the merge, not actually move the branch. (HEAD hasn't been updated yet, since the merge failed)

更具体地说,假设您已经修改了文件A和B,并且尝试合并一个修改了文件C和D的分支.由于某种原因合并失败,因此您决定中止该操作.您使用git reset --merge.它将C和D带回到它们在HEAD中的状态,但是您对A和B的修改就不存在了,因为它们不是合并尝试的一部分.

To be more concrete, suppose you've modified files A and B, and you attempt to merge in a branch which modified files C and D. The merge fails for some reason, and you decide to abort it. You use git reset --merge. It brings C and D back to how they were in HEAD, but leaves your modifications to A and B alone, since they weren't part of the attempted merge.

我确实认为man git reset确实非常适合-也许您确实需要git的工作方式让他们真正陷入困境.特别是,如果您花时间仔细阅读它们,则这些表详细列出了所有各种选项和案例的索引和工作树中的文件状态,这些表将非常有帮助. (但是,是的,它们非常密集-他们以非常简洁的形式传达了上述大量信息.)

I do think man git reset is really quite good for this - perhaps you do need a bit of a sense of the way git works for them to really sink in though. In particular, if you take the time to carefully read them, those tables detailing states of files in index and work tree for all the various options and cases are very very helpful. (But yes, they're very dense - they're conveying an awful lot of the above information in a very concise form.)

您提到的奇怪符号"(HEAD^HEAD~1)只是用于指定提交的简写形式,而不必使用像3ebe3f6这样的哈希名称. 指定修订版"中已完整记录了该文档git-rev-parse的手册页中的部分,其中包含许多示例和相关语法.插入符号和波浪号实际上表示不同的事物:

The "strange notation" (HEAD^ and HEAD~1) you mention is simply a shorthand for specifying commits, without having to use a hash name like 3ebe3f6. It's fully documented in the "specifying revisions" section of the man page for git-rev-parse, with lots of examples and related syntax. The caret and the tilde actually mean different things:

  • HEAD~HEAD~1的缩写,表示提交的第一父级. HEAD~2表示提交的第一父级的第一父级.将HEAD~n视为"n在HEAD之前提交"或"HEAD的第n代祖先".
  • HEAD^(或HEAD^1)也表示提交的第一父级. HEAD^2表示提交的 second 父级.请记住,普通的合并提交有两个父级-第一个父级是merged-into提交,第二个父级是已合并的提交.通常,合并实际上可以有任意多个父母(章鱼合并).
  • ^~运算符可以串在一起,例如HEAD~3^2(HEAD的第三代祖先的第二个父级,HEAD^^2),<<的第一个父级的第二个父级c7>,甚至是HEAD^^^,等同于HEAD~3.
  • HEAD~ is short for HEAD~1 and means the commit's first parent. HEAD~2 means the commit's first parent's first parent. Think of HEAD~n as "n commits before HEAD" or "the nth generation ancestor of HEAD".
  • HEAD^ (or HEAD^1) also means the commit's first parent. HEAD^2 means the commit's second parent. Remember, a normal merge commit has two parents - the first parent is the merged-into commit, and the second parent is the commit that was merged. In general, merges can actually have arbitrarily many parents (octopus merges).
  • The ^ and ~ operators can be strung together, as in HEAD~3^2, the second parent of the third-generation ancestor of HEAD, HEAD^^2, the second parent of the first parent of HEAD, or even HEAD^^^, which is equivalent to HEAD~3.

这篇关于用简单的英语来说,"git reset"是什么意思?做?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆