以下命令引起的更改是否可以被撤销?如果可以,该如何操作?
git reset --hard HEAD~1
以下命令引起的更改是否可以被撤销?如果可以,该如何操作?
git reset --hard HEAD~1
git repack -d 或 git gc ,但请注意垃圾收集也可能会自动发生),那么您的提交仍然存在-只是不再通过HEAD可达。
您可以尝试通过查看 git fsck --lost-found 的输出来查找您的提交。
Git的新版本有一个称为“reflog”的东西,它是对引用所做的所有更改的日志(而不是对存储库内容所做的更改)。因此,例如,每次切换HEAD(即每次执行 git checkout 以切换分支)都将被记录。当然,您的 git reset 也操作了HEAD,因此也被记录下来。您可以像访问存储库旧状态一样,通过使用@
符号而不是~
来访问您的引用的旧状态,例如 git reset HEAD@{1} 。
我花了一段时间才理解HEAD@{1}和HEAD~1之间的区别,因此在这里进行一些解释。git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog
因此,HEAD~1
表示“转到HEAD当前指向的提交之前的提交”,而HEAD@{1}
表示“转到HEAD指向它当前指向的位置之前所指向的提交”。
这将轻松帮助您找到丢失的提交并恢复它。
分离头指针
如果您不在最新的提交上 - 意味着HEAD
指向历史记录中的先前提交,则称为分离头指针
。
HEAD 没有指向当前分支的末尾。
以下是解决分离 HEAD 的几种方法:
git checkout
git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back
这将检出指向所需提交的新分支。
该命令将检出到给定的提交。
此时,您可以创建一个分支并从这个点开始工作。
# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>
# create a new branch forked to the given commit
git checkout -b <branch name>
git reflog
您可以随时使用 reflog
。
git reflog
将显示更新了HEAD
的任何更改,并检出所需的reflog条目将把HEAD
设置回此提交。
每次修改HEAD都会在reflog
中创建一个新条目
git reflog
git checkout HEAD@{...}
这将使你回到所需的提交
git reset HEAD --hard <commit_id>
"将"您的头指向所需的提交。
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
注意:(自Git 2.7起)
你也可以使用git rebase --no-autostash
。
git revert <sha-1>
撤销指定的提交或提交范围。
reset命令将“撤销”给定提交中所做的任何更改。
一个新的提交将包含撤消补丁,而原始提交也将保留在历史记录中。
# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>
这个模式图说明了每个命令的作用。
你可以看到 reset && checkout
修改了 HEAD
。
git reset HEAD --hard <commit_id>
的示例来源于 https://dev59.com/im855IYBdhLWcg3w1oLa#4114122 - 如果是这样的话,请编辑并加上归属。 - Rob我知道这是一个旧的主题...但是由于很多人正在寻找在Git中撤消操作的方法,我仍然认为在这里继续提供提示可能是个好主意。
当你在git gui中执行“git add”或将任何东西从左上角移动到左下角时,文件的内容会被存储在一个blob中,文件的内容可以从该blob中恢复。
因此,即使文件还没有提交,也可以从blob中恢复文件,但是必须已经添加到版本控制中。
git init
echo hello >> test.txt
git add test.txt
现在已经创建了 blob,但它是通过索引引用的,因此在重置之前不会在 git fsck 中列出。所以我们进行重置...
git reset --hard
git fsck
你将获得一个悬挂的Blob ce013625030ba8dba906f756967f9e9ca394464a
git show ce01362
会将文件内容“hello”返回给您。
为了找到未被引用的提交,我在某个地方发现了一个提示。
gitk --all $(git log -g --pretty=format:%h)
我在 Git GUI 中使用它作为工具,非常方便。
我写了一个小脚本,使查找所需的提交更加容易:
git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'
是的,可以使用awk或类似工具使其更美观,但它很简单,而且我只需要它。也许可以为其他人节省30秒。
https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c
基本上,您需要运行:for blob in $(git fsck --lost-found | awk ‘$2 == “blob” { print $3 }’); do git cat-file -p $blob > $blob.txt; done
然后手动痛苦地重新组织你的文件到正确的结构中。
要点:如果你不完全明白git reset --hard
的工作原理,请不要使用它,最好避免使用。
git reflog
命令和回到上一个 HEAD
6a56624 (HEAD -> master) HEAD@{0}: reset: 移动到 HEAD~3
1a9bf73 HEAD@{1}: 提交:在模型生成二进制文件中添加更改
我的问题与这个几乎相同。在输入 git reset --hard
命令之前,我有未提交的文件。
幸运的是,我成功地跳过了所有这些资源。在我注意到我可以撤消 (ctrl-z
在Windows / Linux上,cmd-shift-z
在Mac上) 之后。我只想把这加到上面所有答案中。
注意,无法撤消未打开的文件。
ctrl-z
? - BPSgit reset --hard - 你可以使用这个命令来撤销一个提交,并且之后可以从远程仓库重新获取所有内容。
--hard
会丢弃未提交的更改。由于这些更改未被 Git 跟踪,因此无法通过 Git 恢复它们。 - Zaz--hard
。相反,只需使用git reset
开始 - 如果出现错误,它会提醒你--hard
的实际含义... - undefined