检查未保存的更改

时间:2014-01-28 16:58:30

标签: git

我已经不情愿地从分支develop切换到分支analytics,在那里我有未保存的更改。现在我正在尝试切换回analytics分支并收到以下错误:

error: The following untracked working tree files would be overwritten by checkout:
application/db/some.sql
modules/analytics/config/database.php

如何在不丢失数据的情况下解决问题?

3 个答案:

答案 0 :(得分:2)

您看到的错误消息表明相关文件未在当前分支中进行跟踪,但在您要切换到的分支中进行跟踪。

以下是一个例子,仅使用一个文件:

$ git checkout -b dev  # create new branch dev (I was on master)
Switched to a new branch 'dev'
$ echo contents > dev-file
$ git status
On branch dev
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    dev-file

nothing added to commit but untracked files present (use "git add" to track)
$ git add dev-file 
$ git commit -m 'dev-file is tracked in dev'
[dev 24e6171] dev-file is tracked in dev
 1 file changed, 1 insertion(+)
 create mode 100644 dev-file

现在有一个新文件dev-file,在分支dev中进行跟踪。

$ git checkout master # get back to situation without dev-file
Switched to branch 'master'
$ ls
LICENSE.txt x.txt

我们发现此处不存在dev-file。让我们来创造它。

$ echo contents > dev-file
$ git checkout dev
error: The following untracked working tree files would be overwritten by checkout:
    dev-file
Please move or remove them before you can switch branches.
Aborting
$ 

问题变成了,你想对文件做什么

在这种情况下,我们使用相同的内容创建了dev-file,如果/当我们设法git checkout dev时。我们可以看到与git diff进行比较:

$ git diff dev:dev-file dev-file
$ 

如果我们用不同的内容替换此未跟踪的文件(请记住,此时我们仍然在master上),并尝试相同的git diff,我们和#39;看到他们不匹配:

$ echo different-contents > dev-file
$ git diff dev:dev-file dev-file
diff --git a/dev-file b/dev-file
index 12f00e9..462c93f 100644
--- a/dev-file
+++ b/dev-file
@@ -1 +1 @@
-contents
+different-contents
$ 

但问题不是真的&#34;他们是否匹配&#34;,而是&#34;你想对这种情况做些什么&#34; (其中dev-file未在master中跟踪,在dev中跟踪,并且在我们为&#34;在分支master&#34;)时存在于工作目录中。< / p>

你可以:

  1. git addgit commit它(使其在当前分支上进行跟踪,在本例中为master):它现在通过新提交永久保存;
  2. 完全删除文件(在分支master上时),以便git checkout dev成功,然后git checkout dev;
  3. 使用git checkout -f dev清除文件并立即进入分支dev(与方法2相同);
  4. 将文件保存在常规提交以外的其他位置:例如,使用aaronmallen's answer中的git stash -u,或者手动将其复制到存储库之外的某处;
  5. 发明了一些其他解决方案。 : - )
  6. 方法2和3简单地清除当前分支上的版本,将其替换为分支dev上的版本。如果git diff说当前版本和dev版本之间没有区别,那么您显然没有丢失过程中的任何实际文件内容(因为它保留在分支{ {1}})。如果dev表示 存在差异,那么您将失去非git diff版本。

    在任何一种情况下,如果你切换回dev,文件将会消失:

    master

    (它回到$ git checkout -f dev Switched to branch 'dev' $ cat dev-file contents 中的版本。)

    dev

    (它已经消失了。我们总是可以在$ git checkout master Switched to branch 'master' $ cat dev-file cat: dev-file: No such file or directory 中检索版本,但我们之前放入的dev已经消失了。)

    如果使用different-contents保存未跟踪的文件,您将有一个可以从中恢复未跟踪文件的位置。像这样使用git stash -u会节省很多东西;请参阅git stash -u的文档。

    如果您将未经跟踪的文件完全保存在git之外,那么您将有一个(非git)地方可以从中恢复未跟踪的文件。

    如果您将未跟踪的文件提交到原始分支,那么您将拥有一个实际位置,分支本身(此处为git stash - 从中​​恢复文件,这些文件不再是未跟踪的。

    哪种解决方案最好?没有人回答。也许他们应该被跟踪。也许他们应该像现在一样被跟踪#34;即使在分支master中也许它们应该没有被跟踪(这意味着你必须在分支dev上进行一些操作以使它们在那里变得不受限制:特别是,你会有检查该分支,使用devgit rm --cached,并在该分支中进行新的提交。 Git不能为你做出这个决定,也不能;你需要弄清楚想要用这些文件发生什么。


    编辑:现在我们知道工作目录通过以下方式进入此状态:

    git rm

    我可以补充一点。我不能详细介绍,因为我自己没有尝试过很多细节,也没有使用任何细齿梳子在git中查看索引代码。但是,索引的一个方面是跟踪工作树中的内容。

    它非常昂贵,至少在一个大型项目中,在很多目录中有很多文件中有很多代码来搜索整个工作树 - 但是有一些聪明,git不需要去做。我们假设您的工作树从git --work-tree=/path/outside/here checkout develop 开始,例如您有.。在索引(modules/analytics/config/*)内部,有一些条目跟踪stat有关该目录中文件的信息,如签出。

    Git也知道您(.git/index会报告)git status。然后你调用on branch analytics

    git不是在工作目录中搜索&#34;那里有什么&#34;,而是可以使用索引中的数据假设&#34;什么&#34;那里&#34;是最后签出的。在某些情况下(我不确定哪些情况),git将重新执行git checkout develop并知道索引已过期。在其他人(我再也不确定哪个)中,我可以通过观察看到它没有这样做:它只是假设stat描述了工作树。

    如果您总是使用相同的工作树,使用该(单个)索引,它就会起作用&#34;。如果你使用.git/index将git指向另一个工作树,我已经看到它的作用相当于:&#34;啊,好吧,从--work-tree切换到{{1}我只需要删除这个文件并将其替换为另一个文件&#34; - 这样就可以了。

    您可以强制git使用analytics的其他索引文件。例如,如果您想跟踪develop中的内容,您可以拥有一个名为(例如)GIT_INDEX_FILE=path的文件:

    /path/outside/here

    这还有另外一个问题,.git/index-alt将切换您当前的分支。要解决此问题,请使用# note: this assumes $GIT_DIR is set, as it is with "git-sh-setup" # so let's set it: GIT_DIR=$(git rev-parse --git-dir) || exit alt_index=${GIT_INDEX_FILE-"$GIT_DIR/index"}-alt GIT_INDEX_FILE=$alt_index git --work-tree=/path/outside/here git checkout ... 的替代形式,告诉它​​检出指定分支中的所有文件,但不更改当前分支:

    git checkout ...

    现在&#34;备用索引&#34;跟踪备用工作树,git checkout永远不会更改,因此本地存储库永远不会被搞乱。 (我没有对此进行过测试,但是应该可以使用它 - 我已经计划在其中使用的东西作为&#34;以及如何最好地使用post-receive hooks在服务器上部署版本&#34;。 )

答案 1 :(得分:1)

您可以使用git stash git stash -uGit Stash

答案 2 :(得分:1)

如果目的是获取当前更改并将其应用于分支analytics,那么您应该执行以下操作

git stash
git checkout analytics
git stash pop

stash命令将存储当前分支更改并将工作目录重置为HEAD。切换到分析分支后,您可以使用stash pop重新应用更改。这会将最新的stash命令应用于当前工作目录