The original article was published in zhihu column front grocery store, welcome to pay attention to my column, reprint please indicate the source

Let’s talk about Git instead of the front end. Found that the children now, play a set of frames, until the play of some substantial engineering things can not be. Git is such a great tool, how can training classes ignore its importance?

Let’s talk about how Git works

Many people have only a rudimentary understanding of what Git really is. It is highly recommended that you first understand the core idea and working principle of Git, especially if you have experience with Subversion or Perforce. Instead of going over the principles here, let’s take a look at the simple workflow. Git manages three different boxes — Commit History, INDEX, and Working Directory — with its own framework.

  • Commit HistoryA history that stores snapshots of all committed versions and is referenced by the current branch’s HEAD pointer to the latest commit for that branch.
  • INDEXIndex, also known as staging area. It is a file that holds a snapshot of the list of files to be committed.
  • Working DirectoryThe working directory is a list of files unpacked from the current version of git repository compressed data. So the list of files you see on your local disk for your project’s source code is actually a sandbox that Git opens to you. Feel free to make changes to the file before you move the changes to the staging area and record the snapshot to history.

Now that you understand the implications of all three, let’s try to understand git’s workflow. At the beginning of it all, in the middle of the chaos, we were going to do something big, a couple of keystrokes in Terminal

git init 
Copy the code

HEAD, INDEX, Working Directory. This is what the world looked like in the beginning. Git repositories were like gods of the three worlds. And the Working Directory is the place he assigns you to produce and work, you can create arbitrarily here. For security and management order, we need to send our add and modify files to git repository. Git first marks the modified file into staging, then finds the contents of the staging file and stores it permanently as a snapshot to Git repository, with the HEAD pointer pointing to the latest snapshot.

As shown, the next three steps are summarized

  1. Modify files in the working directory.
  2. Temporary file, a snapshot of the file into the temporary storage area.git add
  3. Commit the update, locate the files in the staging area, and store the snapshot permanently to your Git repository directorygit commit

The basic git workflow is to repeat these three steps over and over again, eventually creating a stack of snapshots in the Git repository, with HEAD pointing to each new release.

Here we create the following files:

├─ md ├─ v1.js ├─ v2.js ├─ v2.jsCopy the code

Form the submission history of the figure below


3aa5dfb v3  (<- HEAD)
        |
5aab391 v2
        |
ff7b88e v1
        |
95d7816 init commit

Copy the code

Use checkout, reset, and revert to checkout the repository directory

Checkout, reset or Revert?

checkout

The idea behind a version control system is to store copies of projects “safely” so that you never have to worry about when your code base will be irretrievably broken. Git Checkout is a convenient way to “unpack” your saved snapshots to your working directory once you’ve established your project history. Git checkout can checkout commits, individual files, and even branches (omitted).

git checkout 5aab391
Copy the code

Check out v2, the current working directory is exactly the same as 5aAB391, you can see that this version of the file editing, running, testing are not saved to git repository. You can git checkout master or git checkout – go back to your original work state.

git checkout 5aab391 v1.js
Copy the code

To check v1.js for v1.js, check v1.js for v1.js file 5aAB391. So it will affect your current working state by overwriting the current v1.js file to version 5aAB391. So unless you know what you’re doing, don’t do it lightly. Git checkout HEAD v1.js, or git checkout — v1.js

Reset to reset

Just like Git checkout, git reset has many uses.

git reset <file>
Copy the code

Removes a specific file from the staging area without changing the working directory. It uncaches the file without overwriting any changes.

git reset
Copy the code

Resets the staging area to match the last commit, but the working directory remains the same. It cancels the staging of all files without overwriting any changes, giving you a chance to reset the staging snapshot.

git reset --hard
Copy the code

Adding the –hard flag tells Git to reset the cache and working directory changes, that is, to clear out your staging first and then all your unstaging changes, so make sure you want to throw away all local work before using it.

git reset <commit>
Copy the code

Moves the current branch’s pointer HEAD to, resets the cache to the commit, but does not change the working directory. All subsequent changes remain in the working directory, allowing you to resubmit the project history with a cleaner, atomic snapshot.

git reset --hard <commit>
Copy the code

Move the current branch’s pointer HEAD to, reset both the cache and the working directory to this commit. Not only does it clear up uncommitted changes, it also clears up all subsequent commits.

Git Reset can discard changes to your current working directory by de-caching or canceling a set of commits, which can be risky. Let’s start with a relatively safe way to revert

Revert to cancel

Git Revert is used to undo a committed snapshot. But the implementation is completely different from reset. By figuring out how to undo the changes introduced by the commit, and then adding a new commit at the end that undoes the changes, rather than removing the commit from the project history.

git revert <commit>
Copy the code

A new commit that undoes the introduced changes is generated and applied to the current branch.

Such as:

81f734d commit after bug
        |
3a395af bug
        |
3aa5dfb v3  (<- HEAD)
        |
5aab391 v2
        |
ff7b88e v1
        |
95d7816 init commit

Copy the code

We have introduced a bug in 3A395AF. If we know the bug is caused by 3A395AF, we can fix the bug through a new submission. Instead, let git Revert help you remove the bug.

git revert 3a395af
Copy the code

results

cfb71fc Revert "bug" | 81f734d commit after bug | 3a395af bug | 3aa5dfb v3 (<- HEAD) | 5aab391 v2 | ff7b88e v1 | 95d7816  init commitCopy the code

At this point, the bug changes are reversed and a new COMMIT is produced, but the commit after bug is not cleared.

So unlike Reset, Revert does not change project history, which is a safe operation for submissions that have already been published to a shared repository. Git Revert allows you to undo any commit in your commit history. Reset removes one commit in history and all subsequent commits.

Another consideration in the revert design is to undo a public repository submission. You can think about it yourself. Let’s illustrate this operation with a hassle (rolling back a bad merge).

merge

Instead of a regular commit, when you merge two branches using git merge

, you get a new merge commit. Git show

Commit 6 dd0e2b9398ca8cd12bfd1faa1531d86dc41021a Merge: d24d3b4 11 a7112 Author: front-end grocery store...Copy the code

Merge: d24d3b4 11a7112 This line shows the version clue of the parent that the two branches were at when they merged.

For example, in the above project we opened a dev branch and did some operations, and now the branch looks like this:

init -> v1 -> v2 -> v3  (master)
           \      
            d1 -> d2  (dev)
Copy the code

When we’re done with dev

#git:(dev)
git checkout master 
#git:(master)
git merge dev
Copy the code

At this time, a Merge Commit Faulty Merge is formed

init -> v1 -> v2 -> v3 -- faulty merge  (master)
           \            /
            d1  -->  d2  (dev)
Copy the code

Faulty Merge Has two parents, V3 and D2.

Roll back the wrong merge

After this merge, development continued in Dev, and another wave of people merged code into master from other branches. It goes like this:

init -> v1 -> v2 -> v3 -- faulty merge -> v4 -> vc3 (master)
        \  \            /                     /
         \  d1  -->  d2  --> d3 --> d4  (dev)/
          \                                 / 
           c1  -->  c2 -------------------c3 (other)
Copy the code

Merge may have introduced a bug to the shared branch master. This bug causes other students in the team to fail the test, or it is an online bug, if it is not fixed in time, the boss will scold.

The first thing that comes to mind at this point is rolling back the code, but how? Using a reset? It is impossible to revert because it is too much of a bully to say so, and it can also destroy other people’s code. Revert was originally designed to do just that.

How do you do that? Git revert

git revert

git revert faulty merge
error: Commit faulty merge is a merge but no -m option was given.
fatal: revert failed
Copy the code

This is because Git doesn’t know which branch to keep changes on when trying to undo a merge. So we need to tell Git which branch m or mainline we want to keep.

git revert -m 1 faulty merge
Copy the code

The value of -m can be 1 or 2, corresponding to the order of the parent. 1 represents v3, 2 represents d2, so this operation preserves the changes made by the master branch and undoes the changes merged by the dev branch.

Submit history changed to

init -> v1 -> v2 -> v3 -- faulty merge -> v4 -> vc3 -> rev3 (master)
          \            /                     
           d1  -->  d2  --> d3 --> d4  (dev)
Copy the code

Rev3 is a regular COMMIT, which contains a set of uncommitted actions that dev merged with at Faulty Merge.

This is not the end of the story. Remember that since we discarded the commit from dev before merging with master, the commit from dev before merging with master will not be included. So what to do?

Restore the previous rollback

Commit = commit = commit = commit = commit = commit

git checkout master
git revert rev3
git merge dev
Copy the code

Now the commit history becomes

init -> v1 -> v2 -> v3 -- faulty merge -> v4 -> vc3 -> rev3 -> rev3` -> final merge (master)
          \            /                                               /
           d1  -->  d2  --> d3 --> d4  --------------------------------(dev)
Copy the code

conclusion

Git rollback code: git rollback code: git rollback In addition, Git is an art, it is a very subtle design, when you use it, you will find more and more interesting things, and quietly praise the people who designed Git. I also hope that both beginners and veterans in the front end will remember to learn these basic tools as they chase popular frameworks.

reference

  • The pro git”
  • The reset revelation
  • git-recipes