我可以删除 git commit 但保留更改吗
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15772134/
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
Can I delete a git commit but keep the changes
提问by tanookiben
In one of my development branches, I made some changes to my codebase. Before I was able to complete the features I was working on, I had to switch my current branch to master to demo some features. But just using a "git checkout master" preserved the changes I also made in my development branch, thus breaking some of the functionality in master. So what I did was commit the changes on my development branch with a commit message "temporary commit" and then checkout master for the demo.
在我的一个开发分支中,我对代码库进行了一些更改。在我能够完成我正在开发的功能之前,我不得不将我当前的分支切换到 master 来演示一些功能。但是仅使用“git checkout master”就保留了我在开发分支中所做的更改,从而破坏了 master 中的一些功能。所以我所做的是使用提交消息“临时提交”在我的开发分支上提交更改,然后为演示签出 master。
Now that I'm done with the demo and back to work on my development branch, I would like to remove the "temporary commit" that I made while still preserving the changes I made. Is that possible?
现在我已经完成了演示并回到我的开发分支上工作,我想删除我所做的“临时提交”,同时仍然保留我所做的更改。那可能吗?
回答by Gareth
It's as simple as this:
就这么简单:
git reset HEAD^
Note: some shells treat ^
as a special character (for example some Windows shells or ZSH with globbing enabled), so you may have to quote "HEAD^"
in those cases.
注意:某些 shell 将其^
视为特殊字符(例如,某些 Windows shell 或启用了 globbing 的 ZSH),因此"HEAD^"
在这些情况下您可能需要引用。
git reset
without a --hard
or --soft
moves your HEAD
to point to the specified commit, without changing any files. HEAD^
refers to the (first) parent commit of your current commit, which in your case is the commit before the temporary one.
git reset
没有--hard
或--soft
移动您HEAD
的指向指定的提交,而不更改任何文件。HEAD^
指的是当前提交的(第一个)父提交,在您的情况下是临时提交之前的提交。
Note that another option is to carry on as normal, and then at the next commit point instead run:
请注意,另一种选择是照常进行,然后在下一个提交点运行:
git commit --amend [-m … etc]
which will instead editthe most recent commit, having the same effect as above.
这将改为编辑最近的提交,具有与上述相同的效果。
Note that this (as with nearly every git answer) can cause problems if you've already pushed the bad commit to a place where someone else may have pulled it from. Try to avoid that
请注意,如果您已经将错误提交推送到其他人可能已将其拉出的地方,则这(与几乎每个 git 答案一样)可能会导致问题。尽量避免这种情况
回答by eddiemoya
There are two ways of handling this. Which is easier depends on your situation
有两种处理方法。哪个更容易取决于你的情况
Reset
重启
If the commit you want to get rid of was the last commit, and you have not done any additional work you can simply use git-reset
如果您想删除的提交是最后一次提交,并且您没有做任何额外的工作,您可以简单地使用 git-reset
git reset HEAD^
Takes your branch back to the commit just before your current HEAD. However, it doesn't actually change the files in your working tree. As a result, the changes that were in that commit show up as modified - its like an 'uncommit' command. In fact, I have an alias to do just that.
将您的分支带回当前 HEAD 之前的提交。但是,它实际上并没有更改工作树中的文件。结果,该提交中的更改显示为已修改 - 它就像一个“取消提交”命令。事实上,我有一个别名来做到这一点。
git config --global alias.uncommit 'reset HEAD^'
Then you can just used git uncommit
in the future to back up one commit.
然后您可以git uncommit
在将来使用它来备份一次提交。
Squashing
压扁
Squashing a commit means combining two or more commits into one. I do this quite often. In your case you have a half done feature commited, and then you would finish it off and commit again with the proper, permanent commit message.
压缩提交意味着将两个或多个提交合并为一个。我经常这样做。在您的情况下,您提交了一个已完成的功能,然后您将完成它并使用正确的永久提交消息再次提交。
git rebase -i <ref>
I say above because I want to make it clear this could be any number of commits back. Run git log
and find the commit you want to get rid of, copy its SHA1 and use it in place of <ref>
. Git will take you into interactive rebase mode. It will show all the commits between your current state and whatever you put in place of <ref>
. So if <ref>
is 10 commits ago, it will show you all 10 commits.
我在上面说是因为我想明确表示这可能是任意数量的提交。运行git log
并找到要删除的提交,复制其 SHA1 并使用它代替<ref>
. Git 将带您进入交互式 rebase 模式。它将显示您当前状态和您放置的任何内容之间的所有提交<ref>
。所以如果<ref>
是 10 次提交前,它会显示所有 10 次提交。
In front of each commit, it will have the word pick
. Find the commit you want to get rid of and change it from pick
to fixup
or squash
. Using fixup
simply discards that commits message and merges the changes into its immediate predecessor in the list. The squash
keyword does the same thing, but allows you to edit the commit message of the newly combined commit.
在每次提交之前,它都会有单词pick
. 找到您要删除的提交并将其从 更改pick
为fixup
或squash
。使用fixup
简单的丢弃提交消息并将更改合并到列表中的直接前任中。该squash
关键字做同样的事情,但是,您可以编辑提交的新合并的提交信息。
Note that the commits will be re-committed in the order they show up on the list when you exit the editor. So if you made a temporary commit, then did other work on the same branch, and completed the feature in a later commit, then using rebase would allow you to re-sort the commits and squash them.
请注意,当您退出编辑器时,提交将按照它们在列表中显示的顺序重新提交。因此,如果您进行了临时提交,然后在同一分支上进行了其他工作,并在以后的提交中完成了该功能,那么使用 rebase 将允许您重新排序提交并压缩它们。
WARNING:
警告:
Rebasing modifies history - DONT do this to any commits you have already shared with other developers.
变基会修改历史记录 - 不要对您已经与其他开发人员共享的任何提交执行此操作。
Stashing
藏匿
In the future, to avoid this problem consider using git stash
to temporarily store uncommitted work.
将来,为避免此问题,请考虑使用git stash
临时存储未提交的工作。
git stash save 'some message'
This will store your current changes off to the side in your stash list. Above is the most explicit version of the stash command, allowing for a comment to describe what you are stashing. You can also simply run git stash
and nothing else, but no message will be stored.
这会将您当前的更改存储在您的存储列表中。上面是 stash 命令的最明确的版本,允许使用注释来描述您要存储的内容。您也可以简单地运行git stash
而不执行其他操作,但不会存储任何消息。
You can browse your stash list with...
您可以使用...
git stash list
This will show you all your stashes, what branches they were done on, and the message and at the beginning of each line, and identifier for that stash which looks like this stash@{#}
where # is its position in the array of stashes.
这将向您显示所有的 stash,它们在哪些分支上完成,以及每行开头的消息和该 stash 的标识符,看起来像这样stash@{#}
,其中 # 是它在stash数组中的位置。
To restore a stash (which can be done on any branch, regardless of where the stash was originally created) you simply run...
要恢复存储(可以在任何分支上完成,无论最初创建存储在哪里),您只需运行...
git stash apply stash@{#}
Again, there # is the position in the array of stashes. If the stash you want to restore is in the 0
position - that is, if it was the most recent stash. Then you can just run the command without specifying the stash position, git will assume you mean the last one: git stash apply
.
同样,# 是存储数组中的位置。如果要恢复的存储位于该0
位置 - 也就是说,如果它是最近的存储。然后你可以直接运行命令而不指定存储位置,git 会假设你的意思是最后一个:git stash apply
。
So, for example, if I find myself working on the wrong branch - I may run the following sequence of commands.
因此,例如,如果我发现自己在错误的分支上工作 - 我可能会运行以下命令序列。
git stash
git checkout <correct_branch>
git stash apply
In your case you moved around branches a bit more, but the same idea still applies.
在您的情况下,您在分支周围移动了更多,但同样的想法仍然适用。
Hope this helps.
希望这可以帮助。
回答by Sudhanshu Jain
I think you are looking for this
我想你正在寻找这个
git reset --soft HEAD~1
git reset --soft HEAD~1
It undoes the most recent commit whilst keeping the changes made in that commit to staging.
它撤消最近的提交,同时保留在该提交中所做的更改以进行暂存。
回答by DURGESH
Yes, you can delete your commit without deleting the changes: git reset @~
是的,您可以在不删除更改的情况下删除您的提交:git reset @~
回答by Bar Horing
You're looking for either git reset HEAD^ --soft
or git reset HEAD^ --mixed
.
您正在寻找git reset HEAD^ --soft
或git reset HEAD^ --mixed
。
There are 3 modes to the reset command as stated in the docs:
如文档中所述,重置命令有 3 种模式:
git reset HEAD^ --soft
git reset HEAD^ --soft
undo the git commit
. Changes still exist in the working tree(the project folder) + the index (--cached)
撤消git commit
. 工作树(项目文件夹)+索引(--cached)中仍然存在更改
git reset HEAD^ --mixed
git reset HEAD^ --mixed
undo git commit
+ git add
. Changes still exist in the working tree
撤消git commit
+ git add
。工作树中仍然存在更改
git reset HEAD^ --hard
git reset HEAD^ --hard
Like you never made these changes to the codebase. Changes are gone from the working tree.
就像您从未对代码库进行过这些更改一样。更改从工作树中消失了。
回答by Greg Hilston
For those using zsh, you'll have to use the following:
对于使用 zsh 的用户,您必须使用以下内容:
git reset --soft HEAD\^
git reset --soft HEAD\^
Explained here: https://github.com/robbyrussell/oh-my-zsh/issues/449
在这里解释:https: //github.com/robbyrussell/oh-my-zsh/issues/449
In case the URL becomes dead, the important part is:
如果 URL 失效,重要的部分是:
Escape the ^ in your command
You can alternatively can use HEAD~ so that you don't have to escape it each time.
转义命令中的 ^
你也可以使用 HEAD~ 这样你就不必每次都逃避它。
回答by Wim Feijen
In my case, I already pushed to the repo. Ouch!
就我而言,我已经推送到 repo。哎哟!
You can revert a specific commit while keeping the changes in your local files by doing:
您可以通过执行以下操作,在将更改保留在本地文件中的同时还原特定提交:
git revert -n <sha>
This way I was able to keep the changes which I needed and undid a commit which had already been pushed.
通过这种方式,我能够保留我需要的更改并取消已经推送的提交。
回答by nkharche
Using git 2.9 (precisely 2.9.2.windows.1)
git reset HEAD^
prompts for more; not sure what is expected input here. Please refer below screenshot
使用 git 2.9(准确地说是 2.9.2.windows.1)
git reset HEAD^
会提示更多;不确定这里的预期输入是什么。请参考以下截图
Found other solution git reset HEAD~#numberOfCommits
using which we can choose to select number of local commits you want to reset by keeping your changes intact. Hence, we get an opportunity to throw away all local commits as well as limited number of local commits.
找到了其他解决方案git reset HEAD~#numberOfCommits
,我们可以选择通过保持更改不变来选择要重置的本地提交数量。因此,我们有机会丢弃所有本地提交以及有限数量的本地提交。
回答by Ruslan Osipov
One more way to do it.
另一种方法来做到这一点。
Add commit on the top of temporary commit and then do:
在临时提交的顶部添加提交,然后执行:
git rebase -i
To merge two commits into one (command will open text file with explicit instructions, edit it).
将两个提交合并为一个(命令将打开带有明确说明的文本文件,对其进行编辑)。