Git:从未暂存/未提交的更改在主分支上创建一个分支

1223

背景:我正在主分支上添加一个简单的功能。几分钟后,我意识到这并不简单,最好应该在新分支上工作。

这种情况总是发生在我身上,我不知道如何切换到另一个分支,并将所有未提交的更改带到另一个分支,使得主分支保持干净。我原本以为git stash && git stash branch new_branch就能完成这个任务,但实际上出现了以下问题:

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ echo "hello!" > testing 

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

你知道是否有任何方法可以实现这个吗?


6个回答

1478

无需stash。

更新于2020年 / Git 2.23


Git 2.23新增了switch子命令,旨在消除由checkout的多重用途(切换分支、恢复文件、分离HEAD等)导致的混淆。

从这个Git版本开始,请使用以下命令替换git checkout命令:

git switch -c <new-branch>

行为保持不变。

在2020年更新/ Git 2.23之前


git checkout -b new_branch_name

该命令不会涉及你的本地更改。它只是从当前 HEAD 创建分支并将 HEAD 设置在那里。所以我想这就是你想要的。

--- 编辑以解释 checkout master 命令的结果 ---

你是否因为 checkout master 命令没有丢弃你的更改而感到困惑?

由于更改仅存在于本地,Git 不希望你轻易丢失它们。当切换分支时,Git 不会覆盖你的本地更改。执行 checkout master 命令的结果是:

M   testing

这意味着您的工作文件不干净。 Git 更改了 HEAD,但没有覆盖您的本地文件。这就是为什么您最后的状态仍然显示本地更改,尽管您正在 master 分支上。

如果您确实想要放弃本地更改,则必须使用 -f 强制检出。

git checkout master -f

由于您的更改从未提交,因此您将失去它们。

尝试返回到您的分支,提交更改,然后再次检出主分支。

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

第一次进行检出后,您应该会收到一个M消息, 但在执行checkout master之后就不再出现了, 而且git status应该显示没有修改过的文件。

--- 编辑以消除有关工作目录(本地文件)的混淆 ---

回答您的第一个评论,本地更改只是...嗯,本地的。Git不会自动保存它们,您必须告诉它将它们保存供以后使用。 如果您进行更改并未显式提交或存储它们,则git不会对其进行版本控制。 如果更改HEAD(checkout master),则由于未保存,本地更改不会被覆盖。


40
这里令人困惑的是,git的手册中写道,“git checkout”将“更新工作树中文件以匹配索引或指定树中的版本。”这意味着您的文件系统中的更改将被删除,没有任何机会可以找回。 即使您说它们不会丢失,这仍然让人感到非常不安。我完全不信任这个。 要么文档真的很糟糕,要么git的默认行为确实很危险。在这种情况下,一个人不应该依赖于某些“自动化”的启发式方法来检测是否要保留更改。 - anon
19
如果你要检出一个提交,它将覆盖你的本地更改(如果当前提交和目标提交之间的历史记录涉及到你本地修改的文件),git会拒绝。只有在checkout不与你的本地更改冲突时,checkout才能工作并保留本地更改。我明白你的感受,手册可能应该说“更新工作树中未被修改的文件”。另一方面,Git并不会让你太容易丢失本地更改。git checkout 要么保留你的本地更改,要么如果有冲突就会拒绝。 - Gauthier
6
@Alex git checkout <other_branch> -f。这将没有警告地使你失去本地的更改。 - Gauthier
1
我不明白。根据我的测试,“git checkout -b new-branch-name”只会将已提交的更改放入新分支中。问题是如何将未提交(和未添加)的更改放入新分支中。 - SMBiggs
1
我发现了这个问题:如果我在主分支上删除文件,并创建新的分支(切换到它),那些你已经删除的文件会重新出现。 - Jemshit Iskenderov
显示剩余9条评论

87

尝试:

git stash
git checkout -b new-branch
git stash apply

8
单独执行'git checkout -b new-branch'和这个有什么不同吗? - Adrian Mouat
我不认为这是答案最初的写法,但我可能错了。不幸的是,由于我的工作环境,我过去几年一直在使用Perforce,所以现在无法证实它的准确性。 - Grant Limberg
7
可以使用以下命令代替最后两步骤:git stash branch new-branch。该命令旨在将当前分支的更改储存起来,并基于当前分支创建一个新的分支,以便以后可以返回这些更改。 - rethab
1
git stash不再需要 - kory
当你有一个已经存在的分支,想把所有东西都放在那里时,stash 对我来说是有意义的:(最终 git fetch --all; 来获取远程分支的起源)git stash; git checkout <existing-branch>; git stash apply; - Paolof76
你仍然需要提交它们,以便它们不会显示在主分支中。 - Muhammad Umer

28

你可以做两件事:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

或者
git stash -u
git branch sillyname stash@{0}

(git checkout - <-- 这个横线表示你之前所在的分支的快捷方式 )

(git stash -u <-- -u 表示同时保存未暂存的更改 )


我完成了第二个任务,然后在新建的分支上执行了 git stash pop 命令。 - Ibrahim.H
我喜欢这个,尽管现在git switch更清晰。 - Serve Laurijssen

27
如果你想把当前分支上的未提交更改移动到一个新的分支,请使用以下命令来创建一个新的分支并自动复制未提交的更改。转化为中文后为:

如果您希望将当前分支上未提交的更改移动到新分支,可以使用以下命令创建新分支并自动复制未提交更改。

git checkout -b branch_name

假设当前分支为主分支(master),这将创建一个新的分支,复制未提交更改并切换到新分支。

将文件添加到暂存区并将更改提交到新分支。

git add .
git commit -m "First commit"

由于创建了一个新的分支,在将其推送到远程之前,您需要设置上游。使用以下命令设置上游并将其推送到远程。

git push --set-upstream origin feature/feature/NEWBRANCH

一旦您执行此命令,将在远程创建新分支,并将您的新本地分支推送到远程。

现在,如果您想放弃主分支中未提交的更改,请使用:

git checkout master -f

在检出时,这将丢弃任何未提交的本地更改。


6
虽然与被接受的答案有一些重叠,但这篇文章提供了一个简单的逐步指南,并包括推送新分支所需的操作。简单、清晰、实用。 - Kjartan
这个操作漏掉了 git add . 吗? - Epirocks
@Epirocks 感谢您指出。我会更新答案。 - Maverick

7
如果你正在使用GitHub Windows客户端(就像我一样),并且你想将未提交的更改移动到新分支中,你可以通过GitHub客户端简单地“创建一个新分支”。它会切换到新创建的分支并保留你的更改。 enter image description here

在创建新分支之前,将更改存储起来,以便不保留它们(Mac OS上的版本223)。 - Fernando Gallego

2
在最新的Windows版GitHub客户端中,如果您有未提交的更改,并选择创建一个新分支。它会提示您如何处理这种情况:

enter image description here

如果您只是切换分支也是一样的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接