如何在确保我当前分支的 none 更改被结转的同时检出分支?

How can I checkout a branch while ensuring that none of my current branch's changes are carried over?

我想要切换分支并让 git 始终 设置工作目录内容以反映我要切换到的分支的状态。我正在经历这里所述的行为 https://web.archive.org/web/20160331103129/http://www.gitguys.com/topics/switching-branches-without-committing - git 正在决定是否将某些文件从与我当前分支关联的工作目录转移到我切换到的分支。

** 这似乎与这里所说的冲突https://www.atlassian.com/git/tutorials/using-branches:"Checking out a branch updates the files in the working directory to match the version stored in that branch..."

在某些情况下,我不想 git 做出决定 - 我只想 Git 使工作目录与新分支的状态相匹配。 但是,我不想丢失任何更改。我愿意事先承诺或隐藏。

可能吗?

未提交的更改将保留在您的工作树或索引中,直到您告诉 git 将它们提交到哪里。

git addgit checkoutgit reset 都有一个 --patch 选项。工作流程是,做需要做的事情和在需要记录的地方记录它是不同的任务。很多时候你会发现自己有效地进行了错误修复,在那里你发现一团糟有人通常是我离开了,问题是,正在做工作,做文书工作,但你正盯着工作,确切地知道需要做什么。

git 方式1 是,去做。在您的工作树中全部正确(这本身可能涉及一些探索性分支)

  • 然后构建您首先构建的提交系列,前提是您确切地知道自己一直在做什么。

这是重要的部分。这就是专业的、可发表的作品。让人们感到困惑的是,git 至少对于之前的混乱部分意味着同样多。


1哈哈哈他说"the git way",好像只有一个lol

作为 ,您将需要弄清楚如何处理未跟踪的 and/or 被忽略的文件。

此外,您不得处于冲突合并的中间。

所有这些都有一个简单的解决方案(使用不同的工作树,可能来自不同的克隆,或者如果您的 Git 足够新,则可能来自 git worktree)。但是,如果出于某种原因不希望这样做,则需要考虑以下几点。让我们举一个有点假设的例子,但展示一些现实世界的问题。假设你在 repo project,目前在分支 dev-a:

$ cd project
$ git status
On branch dev-a
You have unmerged paths.
  (fix conflicts and run "git commit") ...

在这种情况下,你真的很卡。你在这里做的任何事情都会失去你的部分合并状态。如果合并后的状态没有什么重要的,可以运行git merge --abort停止合并,把冲突的索引扔掉,回到前面的情况。让我们看看 Git 是否认为一切都干净。

$ git merge --abort
$ git status
On branch dev-a
nothing to commit, working tree clean

显然 一切都 干净。但是等等!

$ cat foo
I am a foo
$ git checkout dev-b
Switched to branch 'dev-b'
$ git status
On branch dev-b
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    foo

nothing added to commit but untracked files present (use "git add" to track)

一切都干净吗?嗯,文件 foo 在分支 dev-a 中被 忽略 ,但在分支 dev-b 中没有,它现在显示为 "untracked"。我们可以用dev-a中的git status --ignored来看:

$ git checkout dev-a
Switched to branch 'dev-a'
$ git status --short --ignored
!! foo

未跟踪的 and/or 被忽略的文件现在将显示为 UU!!(在短输出中 - 长输出如前所述)。

如果您只想删除 被忽略的文件,您可以使用 git clean-x 选项(除了任何常用选项之外)。

如果你想先保存它们,你可以使用git stash -a。隐藏代码将进行三次提交,而不是通常的两次;第三次提交将保留未跟踪和忽略的文件。 (请注意,git stash -u 在第三次提交中仅保存未跟踪的文件,而不是被忽略的文件。)保存文件后,隐藏代码将删除它们,留下干净的文件(如 git clean -fdx ) 工作树。

请注意,在一个分支中被忽略(因此未被取消跟踪)的文件,例如 dev-a,可以被忽略,因此 或者 未被跟踪 在另一个分支中跟踪(但不是两者),例如 dev-bdev-c。如果文件 foodev-a 中被忽略并且你切换到 dev-b 它就变成未跟踪的,正如我们所看到的。但是,如果它在 dev-a 中被忽略并在 dev-c 中被跟踪怎么办?

$ git status --short --ignored
!! foo
$ git checkout dev-c
Switched to branch 'dev-c'
$ cat foo
I am a foo
$ git checkout dev-a
Switched to branch 'dev-a'
$ cat foo
cat: foo: No such file or directory

文件 foodev-c 中被跟踪并在 dev-a 中被忽略,所以当我们从 dev-a 切换到 dev-c 时它被删除(因为那是从 dev-c 的提示提交到 dev-a 需要什么变化):

$ git diff --name-status dev-c dev-a
A       .gitignore
D       foo

这里还有一个非常棘手的案例。请记住 foodev-a 的(提示提交)中 被忽略 dev-b 未跟踪 ,由 dev-c 中的 I am a foo\n 组成。正如我们刚刚看到的,从 dev-a 切换到 dev-cdev-c 中提取了版本。这是真的不管我们在里面放什么:

$ git rev-parse --abbrev-rev HEAD
dev-a
$ echo 'If the foo s.its, wear it' > foo
$ git checkout dev-c
Switched to branch 'dev-c'
$ cat foo
I am a foo

让我们回到 dev-a 并再次把我们扭曲的 Foo Bird 笑话放回去,这一次,让我们逐步 通过 分支(和提示提交)dev-b,其中文件 foo 未被跟踪,而不是被忽略:

$ git checkout dev-a
Switched to branch 'dev-a'
$ echo 'If the foo s.its, wear it' > foo
$ git checkout dev-b
$ git status --short
?? foo
$ git checkout dev-c
error: The following untracked working tree files would be overwritten by checkout:
    foo
Please move or remove them before you switch branches.
Aborting

这是因为 已忽略 文件也是一个 可破坏(值得破坏?)文件,但是 untracked 文件不是。在 Git 的小头脑中,没有 不应该在 git status 期间抱怨 的路径名的概念(即,忽略 git status,并在某些目录中添加 "all" 文件时跳过),但也是 precious(绝不能被 git checkout 破坏)。

在索引中用 --skip-worktree--assume-unchanged 标志标记的文件使所有这些变得更加复杂。我没有测试过这些额外的极端情况——但所有这些都可以通过使用单独的工作树来避免,而不是试图将所有内容都塞进一个单一的工作树中。 (原因是一个单独的工作树也意味着一个单独的索引。git worktree 代码做得很好,或者你可以简单地在本地克隆存储库,它足够聪明,可以在可能的情况下共享文件。)