如何将Git托管项目中的所有本地更改恢复到以前的状态?

How do I revert all local changes in Git managed project to previous state?

我有一个项目,我运行git init。在几次承诺之后,我做了git status,它告诉我一切都是最新的,没有局部变化。

然后我做了几次连续的改变,意识到我想把所有的东西都扔掉,回到我原来的状态。这个命令能帮我吗?

1
git reset --hard HEAD

如果要还原对工作副本所做的更改,请执行以下操作:

1
git checkout .

如果要恢复对索引所做的更改(即,您添加的更改),请执行此操作。警告:这将重置您对大师未执行的所有承诺!:

1
git reset

如果要还原已提交的更改,请执行以下操作:

1
git revert <commit 1> <commit 2>

如果要删除未跟踪的文件(例如,新文件、生成的文件):

1
git clean -f

或未跟踪的目录(例如,新目录或自动生成的目录):

1
git clean -fd


注意:您可能还想运行

1
git clean -fd

作为

1
git reset --hard

不会删除未跟踪的文件,因为git clean会从跟踪的根目录中删除不在git跟踪下的任何文件。警告-小心!先用git clean运行一次试运行,看看会删除什么,这很有帮助。

当您收到错误消息时,这也特别有用

1
~"performing this command will cause an un-tracked file to be overwritten"

当你和你的朋友都添加了一个同名的新文件,但他先将其提交到源代码管理中,而你不在乎删除未跟踪的副本时,就会出现这种情况。

在这种情况下,干运行也将有助于向您显示将被覆盖的文件列表。


再克隆

1
2
3
4
GIT=$(git rev-parse --show-toplevel)
cd $GIT/..
rm -rf $GIT
git clone ...
  • ?删除本地的非推送提交
  • ?还原对跟踪文件所做的更改
  • ?还原已删除的跟踪文件
  • ?删除.gitignore中列出的文件/目录(如构建文件)
  • ?删除未被跟踪且不在.gitignore中的文件/目录
  • ??你不会忘记这种方法的
  • ??浪费带宽

以下是我每天忘记的其他命令。

清洗复位

1
2
git clean -f -d -x
git reset --hard
  • ?删除本地的非推送提交
  • ?还原对跟踪文件所做的更改
  • ?还原已删除的跟踪文件
  • ?删除.gitignore中列出的文件/目录(如构建文件)
  • ?删除未被跟踪且不在.gitignore中的文件/目录

干净的

1
git clean -f -d -x
  • ?删除本地的非推送提交
  • ?还原对跟踪文件所做的更改
  • ?还原已删除的跟踪文件
  • ?删除.gitignore中列出的文件/目录(如构建文件)
  • ?删除未被跟踪且不在.gitignore中的文件/目录

重置

1
git reset --hard
  • ?删除本地的非推送提交
  • ?还原对跟踪文件所做的更改
  • ?还原已删除的跟踪文件
  • ?删除.gitignore中列出的文件/目录(如构建文件)
  • ?删除未跟踪且不在.gitignore中的文件/目录

笔记

确认以上所有内容的测试用例(使用bash或sh):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir project
cd project
git init
echo '*.built' > .gitignore
echo 'CODE' > a.sourceCode
mkdir b
echo 'CODE' > b/b.sourceCode
cp -r b c
git add .
git commit -m 'Initial checkin'
echo 'NEW FEATURE' >> a.sourceCode
cp a.sourceCode a.built
rm -rf c
echo 'CODE' > 'd.sourceCode'

也见

  • git revert作出撤销先前承诺的新承诺
  • git checkout要在提交之前及时返回(可能需要先运行以上命令)
  • git stash与上面的git reset相同,但您可以撤销它。


如果要还原所有更改并与当前远程主控形状保持最新(例如,您发现自分支主控形状之后,主控形状的头已向前移动,并且您的推送被"拒绝"),则可以使用

1
2
git fetch  # will fetch the latest changes on the remote
git reset --hard origin/master # will set your local branch to match the representation of the remote just pulled down.

查看git reflog。它将列出它记住的所有状态(默认为30天),您只需签出所需的状态即可。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ git init > /dev/null
$ touch a
$ git add .
$ git commit -m"Add file a"> /dev/null
$ echo 'foo' >> a
$ git commit -a -m"Append foo to a"> /dev/null
$ for i in b c d e; do echo $i >>a; git commit -a -m"Append $i to a" ;done > /dev/null
$ git reset --hard HEAD^^ > /dev/null
$ cat a
foo
b
c
$ git reflog
145c322 HEAD@{0}: HEAD^^: updating HEAD
ae7c2b3 HEAD@{1}: commit: Append e to a
fdf2c5e HEAD@{2}: commit: Append d to a
145c322 HEAD@{3}: commit: Append c to a
363e22a HEAD@{4}: commit: Append b to a
fa26c43 HEAD@{5}: commit: Append foo to a
0a392a5 HEAD@{6}: commit (initial): Add file a
$ git reset --hard HEAD@{2}
HEAD is now at fdf2c5e Append d to a
$ cat a
foo
b
c
d


在阅读了大量的答案并尝试之后,我发现了各种各样的边缘案例,这意味着有时它们不能完全清除工作副本。

这是我目前的bash脚本,它一直在运行。

1
2
3
4
#!/bin/sh
git reset --hard
git clean -f -d
git checkout -- HEAD

从工作副本根目录运行。


前方危险:(请阅读评论。执行我的答案中建议的命令可能会删除超过您想要的内容)

要完全删除所有文件,包括必须运行的目录

1
git clean -f -d


简单地说

1
git stash

它会消除你所有的本地痛苦。以后你也可以说

1
git stash apply


我也遇到了类似的问题。解决方案是使用git log查找本地提交的哪个版本不同于远程提交。(例如,版本是3c74a11530697214cbcc4b7b98bf7a65952a34ec)。

然后使用git reset --hard 3c74a11530697214cbcc4b7b98bf7a65952a34ec恢复更改。


我找了一个类似的问题,

想要放弃当地的承诺:

  • 已克隆存储库(Git Clone)
  • 切换到dev分支(git checkout dev)
  • 很少提交(git commit-m"commit 1")。
  • 但决定放弃这些本地提交以返回远程(origin/dev)
  • 以下内容也是如此:

    1
    git reset --hard origin/dev

    检查:

    1
    2
    3
    4
    5
    git status  

            On branch dev  
            Your branch is up-to-date with 'origin/dev'.  
            nothing to commit, working tree clean

    现在,本地提交将丢失,返回到上面第1点的初始克隆状态。


    尝试此操作以还原本地分支中未斜接的所有更改

    1
    $ git reset --hard HEAD

    但是如果你看到这样的错误:

    1
    fatal: Unable to create '/directory/for/your/project/.git/index.lock': File exists.

    您可以导航到".git"文件夹,然后删除index.lock文件:

    1
    2
    $ cd /directory/for/your/project/.git/
    $ rm index.lock

    最后,再次运行命令:

    1
    $ git reset --hard HEAD


    您可能不一定想要/需要将您的工作/文件存放在您的工作目录中,而是简单地将它们完全删除。命令git clean会为你做这件事。

    执行此操作的一些常见用例是删除合并或外部工具生成的cruft,或者删除其他文件,以便运行干净的生成。

    请记住,您将希望非常谨慎地使用此命令,因为它是为从本地工作目录中删除未被跟踪的文件而设计的。如果在执行此命令后突然改变主意,就不会返回查看已删除文件的内容。另一个更安全的选择是执行

    git stash --all

    它会把所有的东西都藏起来。这种藏品可以在以后使用。

    但是,如果确实要删除所有文件并清理工作目录,则应执行

    git clean -f -d

    这将删除由于该命令而没有任何项的任何文件和任何子目录。在执行git clean -f -d命令之前要做的一件聪明的事情是运行

    1
    git clean -f -d -n

    它将向您显示执行git clean -f -d后将删除的内容的预览。

    下面是你的选择总结,从最激进到最不激进

    选项1:本地删除所有文件(最具攻击性)

    1
    git clean -f -d

    选项2:预览上述影响(预览最具攻击性)

    1
    git clean -f -d -n

    选项3:存储所有文件(攻击性最小)

    1
    `git stash --all`