Git advanced advanced operations

This article is following the introduction of Git concepts, common commands and workflows to organize and map_TranSad's Blog-CSDN Blog

Some supplements later, learn to summarize some of the more commonly used operations in additional Git operations. So this article assumes that you already have the previous foundation, and I will directly talk about some parts that have not been mentioned.

Detached HEAD

In Git, we usually think of HEAD as a pointer to the current branch, but if you check out (checkout) a reference that is not a local branch (such as a tag (tag), a remote branch, a SHA-1 ID or a Relative references such as main~3), then you will enter a special state called the "detached head pointer" state.

In the "detached head pointer" state, HEAD no longer points to a branch, but directly to a commit. We can think of this state as an "anonymous branch". In this state, you can make commits normally, but those commits don't update any named branches. This state is useful for navigating through commit history. For example, you can check out a specific version of the code, compile and install it, and then switch back to the master branch.

 If you made a commit while in the "detached head" state, and then switch to another branch (eg main), the commits you made in the "detached head" state may be lost. If you want to save commits made in a "detached HEAD" state, you should create a new branch referencing those commits before switching branches. You can use git checkout -b namecommands to create and switch to a new branch. This command will create a new branch and switch the HEAD pointer to this new branch, so that the commits you made in the "detached head pointer" state will not be lost.

If you directly checkout back to the main branch, then the record is lost, because in Git, if a commit is not referenced by any branch or tag, then it may be deleted by Git's garbage collection mechanism after a period of time.

A fox

A brief recap of the basics of rebase: If you use git rebase main on your feature branch, this command will pull all the commits on the feature branch and reapply them on top of the latest commit from the main branch.

If the original commits are no longer referenced by any branch or label, they may be deleted by Git's garbage collection mechanism after a period of time (that is, the odd commits part in the figure). Therefore, if you need to keep the original commits, you should refer to (or save) these commits rebaseby git checkout -b name命令creating a new branch before, because they will not be deleted as long as there are branches referencing them.

Back to the initial state, if you reverse the command, namely: git checkout main git rebase feature, then you will put the commit of the main branch behind your feature branch:

At this time, if you are developing with multiple people, then your local warehouse is different from the main branch of the remote warehouse, which will bring a series of problems, because other people's main branches are still there, so rebase must not be used wrongly In order, secondly, it is more appropriate to use merge for multi-person development. Here's a normal workflow using merge:

  1. First, in your local repository, maincheckout a new branch (for example, feature) from the master branch ( ), and then develop on this new branch.

  2. When your development work is complete, you can switch back to the main branch and then use git merge featurethe command to merge your work into the main branch. This operation creates a new merge commit.

  3. Then, you can push the master branch to the remote repository, and then create a pull request (pull request) in the remote repository. This pull request shows your changes and asks other members of the project to review your code and merge your changes into the project's master branch.

Now let's go back to rebase and talk about other advanced operations.

git rebase --interactive

git rebase --interactive is a command that allows users to interactively perform more complex operations on the commit history, including compression ( squashing ), splitting ( splitting ), deleting ( deleting ) commits, etc.

Let's start with a simple example: when executed git rebase -i main( featureon a branch), Git will open a text editor listing all maincommits that will be moved (i.e. applied to the branch), such as:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

Before each commit pick, the commit will be used in this rebase. You can change the order in which commits are executed by adjusting the order of these lines. These commits are performed top-to-bottom (in reverse order as seen in the log), so the commits are 33d5b7aadded to mainthe branch first. If you delete a line here, the corresponding commit is discarded. If you delete all rows, then the rebase operation will be aborted. After you save and close the file, Git will perform the rebase operation according to your instructions.

Squashing Compression

To "squash" a commit is to combine a series of commits into a single commit. This can be very useful when merging feature branches into development branches. You may have a large number of small commits that, when merged into the develop branch, can be confusing for other developers to read. Here's a code example: Assuming the second and third commits fix minor issues in the first commit, you can use the squashcommand to merge them into a single commit.

pick 33d5b7a Message for commit #1
squash 9480b3d Message for commit #2
squash 5c67e61 Message for commit #3

 

When you select squasha commit, Git incorporates the changes from that commit into the previous (i.e. above) commit. In your example, changes 9480b3dfrom 5c67e61both commits will be merged into 33d5b7athis commit. This means that the changes from all three commits will be squashed into a new commit. Git will then open an editor and let you write a new commit message for the new merged commit. This message usually defaults to the collection of all squashed commit messages, but you can edit it as needed. Finally, when you save and close the editor, Git will complete the rebase operation, and there will be only one new commit containing all the changes in your commit history, and the original three commits will no longer exist.

splitting

To "split" a commit is to break a commit into separate commits. This can be useful if there are too many different changes made in one commit. By splitting that commit into one or more separate commits, your version history becomes more granular and easier to read and modify. Here's a code example: Suppose you want to split the second commit into two separate commits, you can use editthe split command.

pick 33d5b7a Message for commit #1
edit 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

Git will first execute your first commit (33d5b7a), then apply the second commit (9480b3d), when it finds that you used edit for the second commit, git then puts you in the console. From there, you can use git reset HEAD~a mixed reset of that commit, which essentially undoes that commit and leaves the modified files unstaged. Now, you can stage and commit files separately into several commits. for example:

$ git add file_for_first_commit
$ git commit -m ‘first commit message’
$ git add file_for_second_commit
$ git commit -m ‘second commit message’
$ git rebase --continue

When you finish processing the edit command, git will process the last commit (5c67e61).

delete delete

To "delete" a commit is to remove a commit from the commit history. Assuming the third commit is problematic, you can dropdelete it with the command:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
drop 5c67e61 Message for commit #3

After saving and closing the file, Git applies the changes and puts you back in the editor to merge the commit message. After saving, Git will perform a rebase according to your instructions.

It's important to note that because of the way Git builds commit objects, deleting or changing a commit will cause all commits that follow it to be rewritten. The further back in the repository history you go, the more commits you need to rebuild. This can cause a lot of merge conflicts if there are many commits later in the sequence that depend on the commit you just removed. In the example above we just deleted the last commit, so that's fine.

Some other git rebase --interactive commands:

  • p, pick <commit> = use commit
  • r, reword <commit> = use commit, but edit the commit message
  • e, edit <commit> = use commit, but stop for amending
  • s, squash <commit> = use commit, but meld into previous commit
  • f, fixup <commit> = like "squash", but discard this commit's log message
  • x, exec <command> = run command (the rest of the line) using shell
  • b, break = stop here (continue rebase later with 'git rebase--continue')
  • d, drop <commit> = remove commit
  • l, label <label> = label current HEAD with a name
  • t, reset <label> = reset HEAD to a label
  • m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] = Create a merge commit using the original merge commit's message (or the oneline, if no original merge commit was specified). Use -c <commit> to reword the commit message.

Git commit --amend

Finally, add amend, the amend keyword is also very useful, probably if you want to update your last submission, you can use the git commit --amend -m “message for updated commit”command. This command will add your changes to the last commit and update the commit message.

Guess you like

Origin blog.csdn.net/weixin_44492824/article/details/130653022