Git 已签出未保存的更改

Git 已签出未保存的更改,git,Git,我无意中从分支分析切换到分支开发,在那里我有未保存的更改。现在我尝试切换回分析分支,并得到以下错误: error: The following untracked working tree files would be overwritten by checkout: application/db/some.sql modules/analytics/config/database.php 如何在不丢失数据的情况下修复问题?您可以使用git stashgit stash-u 您可以使用git

我无意中从分支
分析
切换到分支
开发
,在那里我有未保存的更改。现在我尝试切换回
分析
分支,并得到以下错误:

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

如何在不丢失数据的情况下修复问题?

您可以使用git stash
git stash-u

您可以使用git stash
git stash-u

如果目的是获取当前更改并将其应用于分支
分析
,则应执行以下操作

git stash
git checkout analytics
git stash pop

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

如果目的是获取当前更改并将其应用于分支
分析
,则应执行以下操作

git stash
git checkout analytics
git stash pop

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

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

下面是一个仅使用一个文件的示例:

$ 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文件
。让我们创建它

$ 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文件
,如果我们设法
git checkout dev
的话,该文件将具有相同的内容。我们可以看到,与git diff相比:

$ git diff dev:dev-file dev-file
$ 
如果我们用不同的内容替换此未跟踪文件(请记住,此时我们仍在
master
),并尝试相同的
git diff
,我们将看到它们不匹配:

$ 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
$ 
然而,问题不是真正的“它们匹配吗”,而是“对于这种情况,您想做些什么”(在这种情况下,dev文件在
master
中未被跟踪,在
dev
中被跟踪,并且在我们“在分支
master
上”时存在于工作目录中)

你可以:

  • git add
    git commit
    它(在当前分支上跟踪它,在本例中为
    master
    ):它现在通过新提交永久保存
  • 完全删除文件(在分支
    master
    上时),以便
    git checkout dev
    将成功,然后
    git checkout dev
  • 使用
    git checkout-f dev
    一次性清除文件并进入分支
    dev
    (与方法2相同)
  • 将文件保存在常规提交之外的其他位置:例如,使用中的
    git stash-u
    ,或者手动将其复制到存储库之外的某个位置
  • 发明其他解决方案。:-) 方法2和3只需删除当前分支上的版本,将其替换为分支
    dev
    上的版本。如果
    git diff
    说当前版本和
    dev
    -version之间没有区别,那么显然在这个过程中没有丢失任何实际的文件内容(因为它保存在分支
    dev
    中)。如果
    git diff
    表示存在差异,您将丢失非
    dev
    版本

    但是,无论哪种情况,如果切换回
    主控
    ,文件将消失:

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

    (它不见了。我们总是可以在
    dev
    中检索版本,但我们先前放入其中的
    不同内容也不见了。)

    如果使用
    git stash-u
    保存未跟踪的文件,则可以从中恢复未跟踪的文件。像这样使用
    git stash-u
    可以节省很多东西;请参阅git stash的文档

    如果您将未跟踪的文件完全保存在git之外,您将有一个(非git)位置来恢复未跟踪的文件

    如果您将未跟踪的文件提交到原始分支中,实际上您将有一个位置,分支本身,这里是
    master
    ——从中恢复不再未跟踪的文件

    哪一个是最好的解决方案?没有人回答。也许他们应该被追踪。也许他们应该像现在这样“半途而废”。甚至在branch
    dev
    中也应该取消对它们的跟踪(这意味着您必须在branch
    dev
    上执行一些操作才能使它们在那里取消跟踪:特别是,您必须签出该分支,使用
    git rm--cached
    git rm
    ,并在该分支中进行新的提交)。吉特不能为你做这个决定,我也不能;您需要弄清楚这些文件会发生什么


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

    git --work-tree=/path/outside/here checkout develop
    
    我可以补充一点。我不能说得太详细,因为我自己也没有做过太多的实验,也没有用任何形式的细细梳理过git中的索引代码。但是,索引的一点是跟踪工作树中的内容

    搜索整个工作树是非常昂贵的,至少在一个大型项目中,有很多代码,有很多文件,有很多目录,但由于一些聪明,git不必这样做。假设您的工作树从
    开始,您有
    模块/analytics/config/*
    。在索引(
    .git/index
    )中,有一些条目跟踪该目录中已签出的文件的信息

    Git还知道您(正如
    Git status
    将报告的那样)正在分支分析中
    
    
    git --work-tree=/path/outside/here checkout develop
    
    # 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_INDEX_FILE=$alt_index git --work-tree=/path/outside/here checkout branchname -- .