Move Existing, Uncommitted Work to a New Branch in Git – 在Git中把现有的、未提交的工作移到新的分支上

最后修改: 2022年 5月 10日

1. Overview

1.概述

Git is a quite popular version control system today.

Git是当今相当流行的版本控制系统。

In this quick tutorial, we’ll explore how to move existing but uncommitted changes to a new branch.

在这个快速教程中,我们将探讨如何将现有的但未提交的修改转移到新的分支。

2. Introduction to the Problem

2.对问题的介绍

First of all, let’s think about the typical workflow of adding a new feature to a Git managed project:

首先,让我们想一想在Git管理的项目中添加一个新功能的典型工作流程。

  • Create a new feature branch, say feature, and then switch to that branch
  • Implement the feature and commit it to our local repository
  • Push to the feature branch to the remote repository and create a pull request
  • After other teammate’s review, the new change can be merged into the master or release branch

However, sometimes, we’ve started making changes but forgotten about creating a new feature branch and switching to it. As a result, we may realize that we’re on the wrong branch – for instance, the master branch – when we’re going to commit our changes.

然而,有时我们已经开始做修改,却忘记了创建一个新的特性分支并切换到它。结果,当我们要提交修改时,可能会意识到我们在错误的分支上–例如,master分支。

Therefore, we need to create a new feature branch and move the uncommitted work to the new branch. Moreover, the master branch shouldn’t be modified.

因此,我们需要创建一个新的特性分支,并将未提交的工作转移到新的分支。此外,master分支不应该被修改。

An example may explain this scenario quickly. Let’s say we have a Git repository called myRepo:

一个例子可以快速解释这种情况。假设我们有一个名为myRepo的 Git 仓库。

$ git branch
* master

$ git status
On branch master
nothing to commit, working tree clean

As we can see from the output above, we’re currently on the master branch. Also, the working tree is clean.

从上面的输出可以看出,我们目前是在master分支上。另外,工作树是干净的。

Next, let’s make some changes:

接下来,让我们做一些改变。

$ 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")

As the output above shows, we’ve added a new file, a-new-file.txt, and changed the content of Readme.md. Now, we realize that the work should be committed to a feature branch instead of the master branch.

如上面的输出所示,我们添加了一个新文件,a-new-file.txt,并修改了Readme.md的内容。现在,我们意识到,这项工作应该提交到特性分支,而不是master分支。

Next, let’s see how to move the changes to a new branch and keep master unchanged.

接下来,让我们看看如何将改动转移到一个新的分支,并保持master不变。

3. Using the git checkout Command

3.使用git checkout命令

The git checkout -b <BranchName> command will create a new branch and switch to it. Moreover, this command will leave the current branch as it is and bring all uncommitted changes to the new branch.

git checkout -b <BranchName>命令将创建一个新的分支并切换到它。此外,该命令将保留当前分支,并将所有未提交的修改带到新的分支

Next, let’s test the git checkout command on our myRepo project:

接下来,让我们在我们的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")

As the commands above show, we’ve created the feature1 branch and moved all uncommitted changes from master to feature1. Next, let’s stage and commit the changes:

如上面的命令所示,我们已经创建了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

Now, let’s switch back to the master branch and check if we’ve left it unchanged:

现在,让我们切换回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

There is no local change on the master branch, as we can see in the output. Further, there is no new commit on master, either.

正如我们在输出中看到的那样,master分支上没有本地修改。此外,master上也没有新的提交。

4. Using the git switch Command

4.使用git switch命令

As we’ve known, Git’s checkout command is like a Swiss Army knife. The same command can do many different kinds of operations, such as restoring the working tree files, switching branches, creating branches, moving the head, and so on. The usage of the checkout command is pretty overloaded.

正如我们所知,Git的checkout命令就像一把瑞士军刀。同一条命令可以做很多不同的操作,比如恢复工作树文件、切换分支、创建分支、移动头部,等等。checkout命令的用法相当繁杂。

Therefore, Git has introduced the git switch command since version 2.23 to clear some of the confusion from the checkout command’s overloaded usage. As its name implies, git switch allows us to switch between branches. Moreover, we can use the -C option to create a new branch and switch to it in one shot. It works pretty much the same as the git checkout -b command.

因此,Git从2.23版开始引入了git switch命令,以清除checkout命令的超负荷使用带来的一些困惑。顾名思义,git switch允许我们在不同的分支之间切换。此外,我们可以使用-C选项来创建一个新的分支,并一次性切换到它。它的工作原理与git checkout -b命令基本相同。

Next, let’s do the same test as git checkout -b on the myRepo project:

接下来,让我们在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

...

As we can see in the output above, we’re currently on the master branch. This time, we’ve removed the file Readme.md and added a new ReadmeNew.md file.

正如我们在上面的输出中看到的,我们目前在master分支上。这一次,我们删除了文件Readme.md,并添加了一个新的ReadmeNew.md文件。

Next, let’s use the git switch command to move these uncommitted changes to a new branch called feature2:

接下来,让我们使用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

As we can see in the output above, git switch -C creates a new branch feature2 and brings us to feature2. Further, all uncommitted changes have been moved from master to the feature2 branch. Then, we’ve committed the changes to the feature2 branch.

正如我们在上面的输出中看到的,git switch -C 创建了一个新的分支feature2 ,并把我们带到feature2。此外,所有未提交的修改都已经从master移到feature2分支。然后,我们将这些修改提交到feature2分支。

Next, let’s switch back to the master branch and check if it’s unmodified:

接下来,让我们切换回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

As we’ve seen, on the master branch, all changes to the working tree files we made previously have been restored. For example, the removed file Readme.md has come back. Moreover, the git log command shows no new commit on master.

正如我们所看到的,在master分支上,我们之前对工作树文件的所有修改都被恢复了。例如,被删除的文件Readme.md已经回来了。此外,git log命令显示在master上没有新的提交。

5. Conclusion

5.总结

In this article, we’ve addressed a couple of quick ways to move uncommitted changes to a new Git branch. Both commands are pretty straightforward to use:

在这篇文章中,我们讲了几个快速移动未提交的修改到新的 Git 分支的方法。这两个命令的使用都非常简单明了。

  • git checkout -b <NEW_BRANCH>
  • git switch -C <NEW_BRANCH>