Marklai is a senior software engineer with 10 years of experience in software configuration management. He is currently working in CSIG cloud and smart industry business group quality department

Introduction:

Git is a flexible and powerful version management tool that can be used correctly to promote team collaboration and prevent version loss. In practice, however, some developers may intentionally or unintentionally misuse some of Git’s functionality, causing confusion and even loss to the team. Improper code rollback is one of the main problems.

This article focuses on code rollback operations for different scenarios and how to rescue deleted content by mistake.

A typical case

Let’s take a look at the problems that can result from improper code rollback with a real case study from a project team.

(1) Red, yellow and blue work together on the same branch.

(2) Xiao Hong used reset to roll back some content and found that push failed. Finally, she used push-f to succeed. Even worse, push-f indicates that the target is to protect the branch (such as master) and cannot push successfully, so Xiaohong disables the branch protection and makes push-F successful.

(3) A lot of conflicts have been encountered in git pull, and the commit history is messed up!

(4) After a while, you need to look at the source code of a release, but you can’t find the exact code! It had just been reset by Xiao Hong.

Get to know the four working areas of Git

Before reviewing common code rollback scenarios, it’s worth taking a look at Git’s four work areas.

Normally when we clone a code base, the local looks like a directory containing all the project files. It can be logically divided into four work areas:

  • The workspace

    Also known as the working directory or working copy, it is simply the directory containing the project files that we see after clone. Our daily development operations also take place in the workspace.

  • Local repository (.git)

    There is a hidden directory in the workspace. Git, which is the git local repository database. This is where the project files in the workspace are actually checked out, and the changes are eventually committed and recorded to the local repository. Tips: Do not manually modify the contents of the.git directory

  • The staging area

    Also known as the cache, logically located between the workspace and the local repository, the main function is to mark changes. The contents of the staging area are recorded to the local repository by default on the next commit.

  • The remote warehouse

    Team collaboration often requires the designation of a remote repository (usually one or more) with which team members interact to achieve teamwork.

A basic Git workflow is as follows:

  1. inThe workspaceModify file in
  2. Temporary file, file storageThe staging area
  3. Will change fromThe staging areaSubmitted to theLocal repository
  4. fromLocal repositoryPushed to theThe remote warehouse

Common code rollback scenarios

Rollback scenario: Only when the workspace is modified

When a file is being modified in the workspace but not committed to the staging or local repository, you can use Git Checkout — file name roll back and forth to make the changes.

Git can’t track the history of these changes, and they are simply thrown away once they are rolled back.

Example: Viewed using Git status, Changes that have not been committed into staging appear in the “Changes Not Staged for Commit:” section.

Run the following command to roll back workspace changes:

git checkout -- build.sh
Copy the code

Rollback scenario: has been added to the staging area

If you have done git add but have not committed, you can use git reset HEAD file name to rollback. Git status:

Run the following command to roll back changes to the staging area:

git reset HEAD build.sh
Copy the code

After the rollback, the workspace keeps the changes to the file, which can be reedited and recommitted, or git checkout — the file name is discarded entirely.

Rollback scenario: Commit but no push

That is, committed to the local code base, but not pushed to the remote. Git reset

Git reset –hard < commit>

Note that you provide a COMMIT to be rolled back to, and commit records after that commit are discarded.

Example:

Git reset defaults to keeping changes made to discarded records in the workspace for re-editing and resubmission. If the –hard option is added, this part is not reserved and should be used with caution.

Rollback scenario: Modify the last local COMMIT

Sometimes, after the commit, it is found that the modification has not been completely changed, and it is still recorded in a COMMIT. You can do this with “Git reset”, but git also provides an easier way to modify your most recent commit.

The command format is as follows:

Git commit --amend [-m <commit description >]

If the -m

part is not included in the command, Git pulls up the editor to enter the log description. Example:

“Git commit –amend” can only be used to modify local commits that have not been pushed.

Rollback scenario: When a remote device has been pushed

Attention! Use “git revert” instead of “git reset”. Attention! Use “git revert” instead of “git reset”. Attention! Use “git revert” instead of “git reset”.

Important things say three times! Git reset is emphasized because “git reset” erases history and can cause problems when used on records that have already been pushed. “Git Revert” is used to roll back a commit and make a new one without erasing history.

Example:

You can use “Git REVERT — ABORT” to abort the rollback if you run into problems with it.

If you want to roll back a merge COMMIT, you can add “-m < parent number >” to revert, specifying which parent’s records will be used as the main thread after the rollback. A merge COMMIT usually has two parent nodes, sorted numerically by 1 or 2. For a rollback of a “branch merge” commit, “-m 1” is used, using the trunk record as the main line. Rollback merge Commit is a complex topic, and as a general recommendation, avoid rollback merge Commit. For those interested in this topic: github.com/git/git/blo…

Reset vs. Revert

This section will give you an example to help you understand the difference between Git reset and Git Revert.

The initial state of the branch is as follows:

  • If you executegit reset BThe workspace will point toB, subsequent submissions (C, D) are discarded.

If a new commit is made to generate C1, C1 is not associated with C and D.

  • If you executegit revert BRoll back theBA new COMMIT is generated after the content is committedEThe original history will not be modified.

Retrieve deleted content

Git is a powerful version management tool. In general, you don’t have to worry about losing the content you commit to your code base. However, there are some special cases where you have to salvage the content, such as improper reset or the wrong branch deletion. This is where Git reflog comes in handy.

Git reflog is a powerful tool for restoring local history. It can restore almost any local record, such as a commit discarded by reset or a branch deleted.

However, it is important to note that not all records “git reflog” can be recovered, and some cases are still unrecoverable:

  1. Records of non-local operations

    “Git reflog” can manage local workspace records, not non-local (such as other people or on other machines) records.

  2. Uncommitted content

    For example, something that is rolled back only in the workspace or staging area (git checkout — file or Git reset HEAD file).

  3. Too long ago

    “Git reflog” has a limited time limit (90 days by default) on the records that can be retained. In addition, if the active execution of the cleaning command will also be cleared in advance.

Reflog – Reverts to a specific commit

A typical scenario is to perform a reset rollback, then discover that the rollback was wrong and revert to another COMMIT state.

Git reflog git reflog git reflog git reflog git reflog

We can also see from this example that clear, meaningful Commit logs can be very helpful. If the commit log is filled with meaningless statements like “update” and “fix”, then even with a tool like “git reflog”, retrieving the target content can be difficult.

Reflog – Restores a file in a specific COMMIT

Scenario: Run reset to roll back, and some files in the discarded COMMIT are found to be necessary. Solution: Use reflog to find the target COMMIT and run the following command to restore the specific files in the target COMMIT.

Git checkout < target commit>

Example: Reset after rollback to commit 468213d, the build.sh file in the latest state (commit D57f339) is still needed, and the version of the file is restored to the workspace alone.

Reflog – Retrieves local branches that have been deleted by mistake

Git branch -d: “git branch -d” Solution: Run reflog to find the commit before the branch is deleted and rebuild the branch based on the target COMMIT.

Git branch < branch name >

In Reflog records, A commit between “to < branch name >” (e.g. moving from master to dev/pilot-001) and switching to another branch (e.g. moving from dev/pilot-001 to master) is a change on the branch. Select the commit rebuild branches that you want from them.

Example:

Retrieve the deleted branch after merging

As one of Git’s best practices, branch merging can be removed after development to keep the code base clean and only active branches remain. Some students still keep their branches after merging, mainly out of the idea that branches may be useful in the future. You don’t have to. You don’t have to worry about losing content that is already in the main stream and can be retrieved at any time, including rebuilding the development branch from a specific COMMIT. Also, the actual use of the old development branch is really rare, and even if the functionality is buggy, it is fixed and verified by pulling new branches from the trunk.

If you want to rebuild merged branches, you can use the trunk history to find the branch merge record, and then find the branch node, and create a new branch based on the commit, for example:

git branch dev/feature-abc 1f85427

Some suggestions for code rollback

Here are some suggestions for using specific commands:

Also, in general, be careful not to rely too heavily on rollback and avoid using “git push-f “. As one philosopher put it: If you use “git push-f “, you’re doing something wrong!