Best practices for multiple undo operations in Git-related tips

Source: Internet
Author: User
Tags version control system

Objective

I believe you all know that one of the most used features of any version control system is the ability to undo your faulty operation. In Git, "undo" contains a number of slightly different functions. When you make a new submission, Git saves a snapshot of your code base at that particular point in time, and then you can use Git to return to an earlier version of your project.

Undo a "Public" change

scene: you have executed git push , sent your changes to GitHub, and now you realize that one of these commits is problematic and you need to undo that commit.

Method:git revert <SHA>

principle: git revert will produce a new commit, which is reversed (or reversed) with the specified SHA corresponding commit. If the original commit is "material", the new commit is "antimatter"-any content removed from the original commit will be added back in the new commit, and any content added to the original commit will be deleted in the new commit.

This is the safest and most basic undo scenario for Git, because it doesn't change history-so you can now git to push a new "reverse" commit to counteract a commit you've committed incorrectly.

Fix last Commit message

scene: you have a clerical error in the last commit message and have already executed git commit-m "fxies bug #42", but before git push you realize that the message should be "fixes bug #42 ″."

Method: git commit --amend Or git commit --amend -m "Fixes bug #42"

principle: git commit --amend is updated with a new commit and replaces the recent commit, which combines any modifications with the contents of the previous commit. If no changes are currently made, this action will only rewrite the last commit message.

Undo "Local" modifications

scene: a cat walks through the keyboard, accidentally saving modifications, and then destroying the editor. However, you have not yet commit to these modifications. You want to restore all the content in the modified file-just like the last commit.

Method: git checkout -- <bad filename>

principle: git checkout Modifies the files in the working directory to a state that was logged before Git. You can provide a branch name or a specific SHA that you want to return, or by default, Git will assume that you want to checkout the head, the last commit of the current checkout branch.

Remember: any changes you make to "undo" in this way will really disappear completely. Since they have never been submitted, then Git will not help us recover them. Make sure you know what you're throwing away in this operation! (maybe use git diff first to confirm)

Reset "Local" modifications

scene: You've submitted something locally (not pushed yet), but all of these things are bad and you want to undo the previous three submissions-just like they never happened.

Method: git reset <last good SHA> Orgit reset --hard <last good SHA>

principle: git reset will return your code library history to the specified SHA state. It's like these submissions never happened. By default, git reset retains the working directory. In this way, the commit is gone, but the modifications are still on disk. This is a safe choice, but usually we want to "undo" the Commit and modify the content in one step-this is the--hard option.

Restore after "local modifications" are revoked

Scenario: You commit several commits and then undo the changes with git reset--hard (see previous paragraph), and then you realize: you want to restore these changes!

Method: git reflog 和 git reset Orgit checkout

principle: git reflog The history of the recovery project is an excellent resource. You can restore almost anything-anything you commit-just by Reflog.

You may already be familiar with the git log command, which displays a list of commits. Git reflog is similar, but it shows a list of times when the head changes.

Some things to note:

It involves only the head change. The head changes when you switch branches, commit with Git, and undo a commit with Git reset, but when you use git checkout -- <bad filename> undo (as we mentioned earlier), the head does not change-as mentioned earlier, these changes have never been submitted, so Reflog also can't help us recover them.

git reflogwill not remain forever. Git periodically cleans up objects that are "not in use." Don't expect a few months ago the submission is still lying there.

Your reflog is yours, just yours. You can't use it git reflog to restore a commit that another developer didn't push.
Reflog

So... How do you use Reflog to "undo" a Commit before you "restore" it?

It depends on what you want to do:

If you want to accurately restore the history of the project to a point in time, use git reset--hard <SHA>

If you want to rebuild one or more of the files in your working directory and get them back to a point in time, use git checkout <SHA>-<filename>

If you want to resubmit one of these commits to your code base, use git Cherry-pick <SHA>

Another way to take advantage of a branch

scene: you made some submissions and realized that you started check out is the Master branch. You want these to be submitted to another feature (feature) branch.

method: git branch feature , git reset --hard origin/master ,, andgit checkout feature

Rationale: you might be used git checkout -b <name> to creating new branches-This is a popular shortcut to creating new branches and check out immediately-but you don't want to switch branches right away. Here, git branch feature create a new branch called feature and point to your recent commit, but let you check out on the master branch.

Next, git reset --hard reverse the master branch back to Origin/master before submitting any new commits. But don't worry, those commits are still in the feature branch.

Finally, git checkout switch to the new feature branch and make all of your recent work intact.

Timely branching, eliminating tedious

Scenario: You created the feature branch on the basis of the Master branch, but the master branch has lagged behind Origin/master a lot. Now that the master branch has been synchronized with Origin/master, you want the submission on the feature to start now, not from a lot of lag places.

Method: git checkout feature Andgit rebase master

principle: To achieve this effect, you could have passed git reset (without--hard, so you can keep the modifications on disk) and git checkout-b <new branch name> and then resubmit the changes, but in doing so, you Will lose the submission history. We have a better idea.

git rebase masterWill do the following things:

First it will find the branch of your current check out and the common ancestor of the master branch.

It then reset the current check out branch to that common ancestor, storing all previous submissions in a temporary save area.

It then refers the branch of the current check out to the end of master, and then again submits the stored commit to the last commit of the master branch from the temporary Save area.

Large amount of undo/redo

scene: You start to implement a feature in a direction, but halfway you realize that another solution is better. You have made more than 10 submissions, but now you only need a part of them. You want other unwanted submissions to disappear.

Method:git rebase -i <earlier SHA>

principle:- I parameter lets rebase enter "interactive mode". It starts to resemble the Rebase discussed earlier, but it pauses and allows you to modify each submission in detail before you resubmit any submissions.

Rebase-i will open your default text editor, which lists the candidate submissions. As shown below:

The front two columns are the keys: The first is the selected command, which corresponds to the confirmed commit of the SHA in the second column. By default, Rebase-i assumes that each commit is to be used through the pick command.

To discard a commit, just delete the line in the editor. If you no longer need the wrong submissions for the project, you can delete the 1, 3, 4 lines in the previous example.

If you need to keep the content of the commit, instead of editing the commit message, you can use the reword command. Replace the pick in the first column with the reword (or directly with R). Some would think it would be all right to rewrite the commit message here, but that would ignore anything in front of the SHA column, regardless of the-rebase-i. The text behind it is only used to help us remember what 0835fe2 is doing. Once you have completed the rebase-i operation, you will be prompted to enter any commit messages that need to be written.

If you need to combine two commits, you can use the squash or fixup commands as follows:

Squash and fixup will "merge up"-a commit with these two commands will be merged into its previous commit. In this case, 0835fe2 and 6943e85 will be merged into a commit, and 38f5e4e and af67f82 will be merged into another.

If you choose Squash, Git prompts us to give a new commit to the newly merged commit, and fixup the first commit in the consolidated list to the newly merged commit. Here, you know af67f82 is a "finished ..." Commit, so you'll keep a commit message for 38f5e4e as, but you'll write a new message for the new commit that incorporates 0835fe2 and 6943e85.

When you save and exit the editor, Git uses your commit in the order from the top to the bottom. You can change the order of use by modifying the commit order before saving. If you wish, you can also combine af67f82 and 0835fe2 with the following arrangements:

Fix earlier commit

Scenario: You forget to add a file in an earlier commit, and it would be great if an earlier commit could contain the forgotten file. You haven't pushed yet, but this commit is not the most recent, so you can't use a commit--amend.

Method: git commit --squash <SHA of the earlier commit> Andgit rebase --autosquash -i <even earlier SHA>

principle: git commit--squash creates a new commit with a commit message, similar to the squash! Earlier commit. (You can also create a commit with a similar commit message by hand, but a commit--squash can help you save the input work.) )

If you do not want to be prompted to enter a new commit message for a newly merged commit, you can also use Git commit--fixup. In this case, you are likely to use a commit--fixup, because you just want to use the commit message of an earlier commit in rebase.

Rebase--autosquash-i activates an interactive rebase editor, but when the editor is open, any squash! in the commit list and fixup! Commits have been paired to the target commit, as follows:

When using--squash and--fixup, you may not remember the SHA of the commit you want to fix-just remember it was the 1th or 5th commit before. You'll find Git's ^ and ~ operators particularly handy. Head^ is the head's previous commit. The head~4 is head forward 4th-or together, the last 5th commit.

Stop tracking a file

scene: you accidentally add Application.log to the code base, and now every time you run the application, GIT reports uncommitted changes in the Application.log. You put *.login in the. gitignore file, but the file is still in the code base-how can you tell Git to "undo" the tracking of this file?

Method:git rm --cached application.log

principle: although. Gitignore prevents Git from tracking changes to files, or even the existence of files, this is only for files that have never been traced before. Once a file has been added and submitted, Git continues to be concerned about the file's changes. Similarly, if you use Git add-f to force or overwrite. Gitignore, Git will keep track of changes. Then you don't have to use-f to add this file.

If you want to remove a file that should have been ignored from Git's tracking object, git RM--cached removes it from the tracking object, but keeps the file intact on disk. Because it is now ignored, you will not see the file again in git status, nor will you accidentally submit the file's modifications.

Summarize

Above this is how to undo any operation in Git method, I hope the content of this article for everyone's study or work can bring certain help, if there is doubt you can message exchange.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.