为什么 git 不能按路径进行硬/软重置?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11200839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why git can't do hard/soft resets by path?
提问by yao
$ git reset -- <file_path>
can reset by path.
$ git reset -- <file_path>
可以通过路径重置。
However, $ git reset (--hard|--soft) <file_path>
will report an error like below:
但是,$ git reset (--hard|--soft) <file_path>
会报如下错误:
Cannot do hard|soft reset with paths.
回答by Amber
Because there's no point (other commands provide that functionality already), and it reduces the potential for doing the wrong thing by accident.
因为没有意义(其他命令已经提供了该功能),并且它减少了意外做错事的可能性。
A "hard reset" for a path is just done with git checkout HEAD -- <path>
(checking out the existing version of the file).
路径的“硬重置”刚刚完成git checkout HEAD -- <path>
(检查文件的现有版本)。
A soft reset for a path doesn't make sense.
路径的软重置没有意义。
A mixed reset for a path is what git reset -- <path>
does.
路径的混合重置是什么git reset -- <path>
。
回答by Aaron Kent
You can accomplishment what you're trying to do using git checkout HEAD <path>
.
您可以使用git checkout HEAD <path>
.
That said, the provided error message makes no sense to me (as git reset
works just fine on subdirectories), and I see no reason why git reset --hard
shouldn't do exactly what you're asking of it.
也就是说,提供的错误消息对我来说毫无意义(因为git reset
在子目录上工作得很好),而且我认为没有理由git reset --hard
不完全按照您的要求执行。
回答by user
The question howis already answered, I'll explain the whypart.
问题如何已经回答,我将解释为什么部分。
So, what does git resetdo? Depending on the parameters specified, it can do two different things:
那么,git reset 有什么作用呢?根据指定的参数,它可以做两种不同的事情:
If you specify a path, it replaces the matched files in the index with the files from a commit (HEAD by default). This action doesn't affect the working tree at all and is usually used as the opposite of git add.
If you don't specify a path, it moves the current branch head to a specified commit and, together with that, optionally resets the index and the working tree to the state of that commit. This additionalbehavior is controlled by the mode parameter:
--soft: don't touch the index and the working tree.
--mixed(default): reset the index but not the working tree.
--hard: reset the index and the working tree.
There are also other options, see the documentation for the full list and some use cases.When you don't specify a commit, it defaults to HEAD, so
git reset --soft
will do nothing, as it is a command to move the head to HEAD (to its current state).git reset --hard
, on the other hand, makes sense due to its side effects, it says move the head to HEAD andreset the index and the working tree to HEAD.I think it should be clear by now why this operation is not for specific files by its nature - it is intended to move a branch head in the first place, resetting the working tree and the index is secondary functionality.
如果您指定路径,它会将索引中匹配的文件替换为提交中的文件(默认为 HEAD)。此操作根本不会影响工作树,通常用作 git add 的反义词。
如果您不指定路径,它会将当前分支头移动到指定的提交,并且可以选择将索引和工作树重置为该提交的状态。此附加行为由模式参数控制:
--soft:不要接触索引和工作树。
--mixed(默认):重置索引但不重置工作树。
--hard:重置索引和工作树。
还有其他选项,请参阅完整列表和一些用例的文档。当您不指定提交时,它默认为 HEAD,因此
git reset --soft
不会执行任何操作,因为它是将头部移动到 HEAD(到其当前状态)的命令。git reset --hard
,另一方面,由于其副作用,它说将头部移动到 HEAD并将索引和工作树重置为 HEAD。我认为现在应该清楚为什么此操作本质上不适用于特定文件 - 它首先旨在移动分支头,重置工作树,索引是次要功能。
回答by Pascal Nitcheu
Make sure you put a slash between origin or upstream (source) and the actual branch:
确保在原点或上游(源)和实际分支之间放置一个斜线:
git reset --hard origin/branch
or
或者
git reset --hard upstream/branch`
回答by F Pereira
There's a very important reason behind that: the principles of checkout
and reset
.
有背后的一个很重要的原因:原则checkout
和reset
。
In Git terms, checkoutmeans "bring into the current working tree". And with git checkout
we can fill the working tree with data from anyarea, being it from a commit in the repository or individual files from a commit or the staging area(which is the even the default).
在 Git 术语中,checkout 的意思是“带入当前的工作树”。并且git checkout
我们可以用来自任何区域的数据填充工作树,无论是来自存储库中的提交还是来自提交或暂存区(甚至是默认值)的单个文件。
In turn, git resetdoesn't have this role. As the name suggests, it will reset the current ref but alwayshaving the repositoryas a source, independently of the "reach" (--soft, --mixed or --hard).
反过来, git reset没有这个角色。顾名思义,它将重置当前引用,但始终将存储库作为源,独立于“范围”(--soft、--mixed 或--hard)。
Recap:
回顾:
- checkout: From anywhere (index / repo commit) -> working tree
- reset: Repo commit -> Overwrite HEAD (and optionally index and working tree)
- 结帐:从任何地方(索引/回购提交)-> 工作树
- reset: Repo commit -> Overwrite HEAD (以及可选的索引和工作树)
Therefore what can be a bit confusing is the existence of git reset COMMIT -- files
since "overwriting HEAD" with only some files doesn't make sense!
因此,可能有点令人困惑的是存在,git reset COMMIT -- files
因为仅使用某些文件“覆盖 HEAD”是没有意义的!
In the absence of an official explanation, I can only speculate that the git developers found that reset
was still the best name of a command to discard changes made to the staging area and, given the only data source was the repository, then "let's extend the functionality" instead of creating a new command.
在没有官方解释的情况下,我只能推测 git 开发人员发现这reset
仍然是放弃对暂存区所做更改的命令的最佳名称,并且鉴于唯一的数据源是存储库,那么“让我们扩展功能”,而不是创建新命令。
So somehow git reset -- <files>
is already a bit exceptional: it won't overwrite the HEAD. IMHO all such variations would be exceptions. Even if we can conceive a --hard
version, others (for example --soft
) wouldn't make sense.
所以不知何故git reset -- <files>
已经有点例外:它不会覆盖 HEAD。恕我直言,所有这些变化都是例外。即使我们可以构思一个--hard
版本,其他版本(例如--soft
)也没有意义。
回答by Tom Hale
Explanation
解释
The git reset
manuallists 3 ways of invocation:
该git reset
手册列出了 3 种调用方式:
2 are file-wise: These do not affect the working tree, but operate only on the files in the index specified by
<paths>
:git reset [-q] [<tree-ish>] [--] <paths>..
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
1 is commit-wise: Operates on all filesin the referenced
<commit>
, and mayaffect the working tree:git reset [<mode>] [<commit>]
2 是文件方面的:这些不影响工作树,但仅对由 指定的索引中的文件进行操作
<paths>
:git reset [-q] [<tree-ish>] [--] <paths>..
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
1 是 commit-wise:对引用中的所有文件进行操作
<commit>
,并可能影响工作树:git reset [<mode>] [<commit>]
There's no mode of invocation that operates only on specified files andaffects the working tree.
没有仅对指定文件进行操作并影响工作树的调用模式。
Workaround
解决方法
If you want to both:
如果你想两者兼得:
- Reset the index/cache version of a file(s)
- Checkout the file(s) (ie, make the working tree match the index and commit version)
- 重置文件的索引/缓存版本
- 签出文件(即,使工作树与索引和提交版本匹配)
You can use this alias in your git config file:
你可以在你的 git 配置文件中使用这个别名:
[alias]
reco = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #" # Avoid: "fatal: Cannot do hard reset with paths."
You can then do one of:
然后,您可以执行以下操作之一:
$ git reco <paths>
$ git reco <branch/commit> <paths>
$ git reco -- <paths>
(Mnenonic for reco
: re
set && c
hecko
ut)
(助记符reco
:re
set && c
heck o
ut)
回答by Peiti Li
git reset --soft HEAD~1 filenameundo the commit but changes remain in local. filenamecould be -- for all commited files
git reset --soft HEAD~1 filename撤消提交但更改保留在本地。文件名可以是 -- 对于所有提交的文件