An embarrassing incident recently occurred while developing a small requirement for the project. When I finished developing new features, I suddenly realized that I was working on the wrong branch. However, I remember when I was learning About Git there was a Git Stash command to archive the content that was not currently committed and then apply the current archive to the target branch after switching branches. I don’t usually use this command, so I’m a little rusty and need to go back to the documentation.

After a couple of minutes of reviewing the git stash related commands again, the problem was solved smoothly. Because the usual development is to follow the relevant Git process, there is generally no error, and the usual use of git commands are also some common. Part of the reason for this problem is that the project is not a long-term maintenance project. When developing new features, you open the project and think you are still in your own development branch. They didn’t check to see if they were developing the right branch. The deeper reason is that Git is not well mastered. Also just borrow this opportunity, the relevant command again good review, also very good.

There are three things that happen when you develop new features in the wrong branch:

  • The new features have not been implemented locallycommit(Submission), which is what happened to me this time

  • The new functionality has been submitted locally, but not yetpushTo remote warehouse

  • The new functionality has been submitted locally, andpushTo the remote warehouse

Although I encountered the first situation, when I solved this problem, IT was natural for me to think: what should I do if I encountered the other two situations? This article looks at what you should do if you develop new features in the wrong branch in each of the three cases mentioned above.

The new features have not been implemented locallycommit(submitted)

In this case we can use it under the current branch:

git stash
Copy the code

This command means that we temporarily store the changes we are currently making, and then our workspace reverts back to what it was before the new functionality was developed.

At this point we need to switch to the correct work branch and run the command:

git stash apply
Copy the code

This command applies what we temporarily stored to the current branch. So we’re moving the changes from one branch to another.

The two commands above are also the ones I used to solve this problem. I’m not satisfied with just solving this problem. I need to learn more about the git Stash command in detail. The following is a deeper look at what it is and why.

The first thing we need to know is that using the Git Stash command saves our workspace and staging changes, and then removes those changes from the current file and saves them in the archive. So we went back to a clean workspace that had not been modified before.

The git stash push command is equivalent to the git stash push command when no parameter is added. When we use git stash to create a snapshot of the current modification, the command will give the following information:

Saved working directory and index state WIP on <branchname>: <hash> <commit message>
Copy the code

Branchname is the name of your current branch, hash is the hash value of your last commit, and commit Message is the commit information you added to your last commit.

This is used when only one snapshot is currently storedgit stashIf you want to store multiple snapshots in your current branch, it is best to add some explanatory information to each snapshot so that you know what each snapshot does when you use it.

We can use git Stash push -m message to add detailed instructions to each snapshot, such as:

Git Stash Push -m "Add feature 1"Copy the code

After the command line is executed, the following information is displayed on the terminal:

Saved working directory and index state On <branchname>: add feature 1
Copy the code

According to the information displayed by the terminal, we can know which branch the current snapshot is generated in, and with the detailed description of Add feature 1, it will be clearer when used in the future.

When we have a lot of snapshots, we might want to look at the current snapshot list. At this point we can use the Git Stash list to look at the current snapshot list. After running the Git Stash list on your terminal, if you add some snapshots earlier, the following information will be displayed:

stash@{0}: On <branchname>: add feature 1
stash@{1}: On <branchname>: add feature 0
stash@{2}: On <branchname>: <message>
stash@{3}: WIP on <branchname>: 47e52ae <commit message>
stash@{4}: On <branchname>: <message>
Copy the code

From the above information, we can know that the latest snapshot is placed on the top of the stack, so the latest snapshot is placed on the top of the stack.

If we want to see what has changed between the last snapshot and the committed files when the snapshot was created, we can use the git Stash show command. By default, this command displays file differential statistics. If you want to show specific changes, you can use git Stash show -p.

Because we have more than one snapshot, so we also want to see before a snapshot of the with this snapshot was submitted version of the differences, we can at the back of the above command to add a snapshot of the index, for instance if you want to see the add feature above 0 this snapshot file changes, use the following command:

Git stash show stash@{1} #Copy the code

Then it is time to apply (restore) the snapshot. If you want to apply the contents of a snapshot to the current branch, just run the following command:

Git stash apply # Apply the latest snapshot content to the current branch git stash apply stash@{n} # n indicates the specific snapshot indexCopy the code

In this case, the snapshot content can be applied to the current version. Conflicts may occur during the snapshot application. In this case, you need to manually handle the conflicts and submit them again.

Git stash apply can add – the index parameter, this parameter is used in the application of the snapshot, will add already to the staging area (index) of change is still preserved in the staging area, if not add this parameter, all changes will become in the workspace changes (i.e., not stored in the index of state).

We can test it by making a change to a file, then adding the change (using Git add) to the staging area, and then adding a change again, this time not to the staging area. If you run git status, you’ll see the following:

On branch dev
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   20200830/index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   20200830/README.md

Copy the code

When we run the git Stash command and then run the git stash apply command, we see the following:

On branch dev
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   20200830/README.md
        modified:   20200830/index.html

no changes added to commit (use "git add" and/or "git commit -a")

Copy the code

So when the –index parameter is not used, the previous state in the staging area is not saved.

There are other git stash commands as well, such as:

  • git stash drop: Discards a snapshot
  • git stash pop: Applies the latest snapshot to the current branch. If the application succeeds, the snapshot is removed from the snapshot stack
  • git stash clear: Clears all snapshots

Some of the most common git stash commands and operations are described above. If you want to learn more about git-Stash, you can refer to git-Stash.

The above content is mainly in the case of our new development features have not been submitted, when we develop new features have been submitted locally, how do we deal with the situation? So let’s talk about that.

The new functionality has been submitted locally, but not yetpushTo remote warehouse

If the newly developed functionality is already committed locally, but the branch we developed is the wrong branch. At this time, according to the different situation, there are two ways to deal with.

New functionality needs to be added in a new branch

First we need to know which commit the branch is currently in before we add new functionality. You can run the following command:

git log --oneline
Copy the code

Looking at the current branch commit, you can see output with the following:

085095f (HEAD -> master) update 5
47e52ae update 3
14fefac update 2
fd01444 add README.md
3c76ad1 init
Copy the code

Find the commit where the current branch was when we added the new functionality. If it is FD01444, then the next thing we need to do is to point the HEAD pointer to FD01444, which is to reset what our current branch committed to before we developed the new functionality. We need to run the following command:

Git reset fd01444 # fd01444 is the hash value for a commitCopy the code

If the reset mode is not specified, the default is to use –mixed mode, so that all commits after fd01444 will be reset to the uncommitted state. Next we need to migrate these newly developed functions to a new branch. In this case, we can use the following command:

git checkout -b <newbranch>
Copy the code

Now that we have created a new branch and migrated the new functionality, it is time for the normal add and commit operations.

New functionality needs to be added to another branch

If we need to migrate the currently added functionality to another existing branch, the first few steps we need to do are the same as above:

Git reset <commit HashCopy the code

Now we’re back to the state where the new functionality hasn’t been committed yet, so we can continue with the Git Stash commands.

Another way to add functionality that has been committed to the current branch to another branch is to use the git cherry-pick command. Git log –oneline — git log –oneline — git log –oneline

git cherry-pick <commit hash>
Copy the code

This adds functionality that we developed in the other branch to the desired branch. If there are conflicts, you need to handle them manually. Then we go back to the original branch, run git reset

again to reset the committed content, and run the following command:

git checkout -- .
Copy the code

We can also achieve the goal of adding new functionality to another branch by clearing everything that is not added to the staging area in the current branch.

The new functionality has been submitted locally, andpushTo the remote warehouse

Third, we have pushed the new functionality to a remote repository, but we suddenly realize that the new functionality should not be developed in this branch. What should we do in this case?

First we should keep the current workspace unmodified and in a clean state. Otherwise, the undo command will prompt you to commit the changes to the current file or create a snapshot. When the state of our workspace is clean, we can undo.

The first thing we need to know is the status of the commit we should undo. Use git log –oneline to view the commit index you want to undo, and then run the following command:

git revert <commit>
Copy the code

At this point, the command terminal will enter editor mode and let you fill in the submitted information. Of course, you can also use the parameter –no-edit so that the edit mode is not turned on during the undo operation.

If there are a lot of commits that need to be undone, we can use.. Represents a range of committed records. Such as c1.. C2 represents the reachable commit of C2, excluding the reachable commit of C1. Reachable commits refer to the commit itself and the collection of commits in its ancestor chain.

Here’s an example:

. a - b - c - d - HEADCopy the code

If the above represents the commit record of a branch, then for b.. D represents the two submissions c and D. For a.. D is b, C, and D. If you want to learn more about git-rev-list, you can learn more about git-rev-list.

So if we want to quickly undo a range of commits, we can run a command like the following:

git revert 54dc134.. a72d612 --no-editCopy the code

54dc134 is c1, a72d612 is C2, –no-edit means we don’t open edit mode when we run undo.

If we need to undo a remote branch, the first consideration is to usegit revertCommand, becausegit revertThe command does not modify the historical commit record, but simply adds a new commit to the original commit, so there is no loss of code. Use in cooperative situations with multiple peoplegit revertCommand to cancel thepushRemote operations are necessary.

If you have a better solution to these problems, you are welcome to leave a comment below the article, we can discuss together, progress together. If you have any comments and suggestions on the article, you are welcome to leave a message below the article, or put forward here, I will continue to try to improve. You are also welcome to pay attention to my public account guanshan is not difficult to get the latest updates in time.

Reference links:

  • Undoing Commits & Changes
  • git-revert – Revert some existing commits
  • How to revert multiple git commits?
  • Git – how to revert multiple recent commits