1. 概述
现今,Git 是一个非常流行的版本控制系统。在这篇简短教程中,我们将探讨如何将已存在的但未提交的更改移动到新的分支。
2. 问题介绍
首先,让我们考虑一下在 Git 管理的项目中添加新特性的典型工作流程:
- 创建一个新的特性分支,比如
feature
,然后切换到该分支 - 实现功能并在本地仓库中进行提交
- 将更改推送到远程仓库的特性分支,并创建拉取请求
- 在其他队友审查后,新更改可以合并到
master
或release
分支
然而,有时我们可能已经开始做修改,却忘记了创建新特性分支并切换到它。结果,当我们打算提交更改时,可能会发现自己在错误的分支上,例如 master
分支。
因此,我们需要创建一个新的特性分支并将未提交的工作移动到新分支,同时确保 master
分支不受影响。
举个例子来快速说明这种情况:假设我们有一个名为 myRepo
的 Git 存储库:
$ git branch
* master
$ git status
On branch master
nothing to commit, working tree clean
如上所述,我们当前位于 master
分支,工作目录是干净的。
接下来,我们做一些更改:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Readme.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
a-new-file.txt
no changes added to commit (use "git add" and/or "git commit -a")
如上输出所示,我们添加了一个新文件 a-new-file.txt
并修改了 Readme.md
的内容。现在,我们意识到这些工作应该在一个特性分支而不是 master
分支上进行提交。
3. 使用 git checkout
命令
git checkout -b <BranchName>
命令会创建一个新的分支并切换到该分支。此外,此命令会 保留当前分支不变,并将所有未提交的更改带到新分支。
接下来,让我们在 myRepo
项目上测试 git checkout
命令:
$ git branch
* master
$ git co -b feature1
Switched to a new branch 'feature1'
$ git status
On branch feature1
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Readme.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
a-new-file.txt
no changes added to commit (use "git add" and/or "git commit -a")
如上述命令所示,我们创建了 feature1
分支,并将 master
上的所有未提交更改移动到了 feature1
。接着,让我们暂存并提交更改:
$ git add . && git commit -m'implemented feature1'
[feature1 2ffc161] implemented feature1
2 files changed, 2 insertions(+)
create mode 100644 a-new-file.txt
$ git log --abbrev-commit feature1
commit 2ffc161 (HEAD -> feature1)
Author: ...
Date: ...
implemented feature1
commit b009ddf (master)
Author: ...
Date: ...
init commit
现在,让我们回到 master
分支,检查是否未对其进行任何更改:
$ git checkout master
Switched to branch 'master'
$ git status
On branch master
nothing to commit, working tree clean
$ git log --abbrev-commit master
commit b009ddf (HEAD -> master)
Author: ...
Date: ...
init commit
如输出所示,master
分支上的本地更改没有变化,也没有新的提交。
4. 使用 git switch
命令
正如我们所知,Git 的 checkout
命令就像一把瑞士军刀,可以执行多种不同的操作,如恢复工作目录文件、切换分支、创建分支、移动 HEAD 等。checkout
命令的用法相当复杂。
因此,Git 自版本 2.23 开始引入了 git switch
命令,以消除 checkout
命令过度使用带来的部分混乱。顾名思义,git switch
允许我们在分支间切换。此外,我们可以使用 -C
选项 一次创建新分支并切换到它,这与 git checkout -b
命令的效果基本相同。
接下来,让我们在 myRepo
项目上像 git checkout -b
那样进行相同的测试:
$ git branch
feature1
* master
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm ...)
(use "git restore ...)
deleted: Readme.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
ReadmeNew.md
...
如上输出所示,我们目前位于 master
分支。这次,我们删除了文件 Readme.md
并添加了一个新文件 ReadmeNew.md
。
接下来,让我们使用 git switch
命令将这些未提交的更改移动到名为 feature2
的新分支:
$ git switch -C feature2
Switched to a new branch 'feature2'
$ git status
On branch feature2
Changes not staged for commit:
(use "git add/rm ...)
(use "git restore ...)
deleted: Readme.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
ReadmeNew.md
...
$ git add . && git commit -m 'feature2 is done'
[feature2 6cd5933] feature2 is done
1 file changed, 0 insertions(+), 0 deletions(-)
rename Readme.md => ReadmeNew.md (100%)
$ git log --abbrev-commit feature2
commit 6cd5933 (HEAD -> feature2)
Author: ...
Date: ...
feature2 is done
commit b009ddf (master)
Author: ...
Date: ...
init commit
如上输出所示,git switch -C
创建了新分支 feature2
,并将我们带到 feature2
分支。所有未提交的更改已从 master
移动到 feature2
分支。然后,我们在 feature2
分支上提交了更改。
接下来,让我们回到 master
分支并检查是否未被修改:
$ git switch master
Switched to branch 'master'
$ git status
On branch master
nothing to commit, working tree clean
$ ls -1 Readme.md
Readme.md
$ git log --abbrev-commit master
commit b009ddf (HEAD -> master)
Author: ...
Date: ...
init commit
如我们所见,master
分支上,我们之前对工作目录文件所做的所有更改都已恢复。例如,删除的文件 Readme.md
返回了。此外,git log
命令显示 master
上没有新的提交。
5. 总结
本文讨论了几种快速将未提交更改移动到 Git 新分支的方法。这两个命令都非常直观易用:
-
git checkout -b <NEW_BRANCH>
-
git switch -C <NEW_BRANCH>