大家好,我是青空。
Git是现在非常流行的一个版本控制系统。 在本文中我们将探讨如何将现有的但未提交的修改转移到一个新的分支。
问题概述
首先,让我们想一想在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分支。
接下来,让我们看看如何将这些改动转移到新的分支,并保持master不动。
使用 git checkout 命令
git checkout -b 命令将创建一个新的分支并切换到该分支。此外,该命令将保留当前分支,并将所有未提交的修改带到新分支。
接下来,让我们在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分支上没有本地修改。此外,master上也没有新的提交。
使用 git switch 命令
正如我们所知,Git的checkout命令就像一把瑞士军刀。同一条命令可以做很多不同的操作,比如恢复工作树文件,切换分支,创建分支,移动头部,等等。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上没有新的提交。
总结
在这篇文章中,我们解决了几个快速移动未提交的修改到新的 Git 分支的方法。这两个命令都是非常直接的用法。
- git checkout -b <NEW_BRANCH>。
- git switch -C <NEW_BRANCH>。