Learning Git Branching can be said to be the best tutorial so far, address
Click the question mark in the lower right corner to display commonly used commands
1. Submit
git commit
Submit the content and save these changes as a submission record C3, the parent node of C3 is C2
Modify commit information
git commit --amend
A submission record will be generated after each git commit. Using git commit --amend will append the current modification to the latest submission without generating a new submission record. For example,
C2 is submitted here, and the modification is added to C2. C2' is formed, but no new submission record is generated. The submission comments of C2 and C2' are the same, but the hash values are different
2. Create and switch branches
git branch newImage
The newly created branch newImage points to the commit record C1
git checkout newImage
git commit
Switch to the newImage branch, commit C2, * indicates the current branch
Note: In version 2.23 of Git, a new command called git switch was introduced, which will eventually replace git checkout, because checkout is a bit overloaded as a single command (it carries many independent function)
git checkout -b bugFix
Create a new branch bugFix and switch to this branch at the same time, which can be achieved by git checkout -b your-branch-name
3. merge merge
git merge bugFix
Merging the bugFix branch into the current main branch
Merging two branches in Git produces a special commit record, which has two parents. Translated into natural language is equivalent to: "I want to include these two parent nodes themselves and all their ancestors.", main now points to a commit record C4 with two parent nodes
git checkout bugFix
git merge main
Then merge the main branch into bugFix, because main inherits from bugFix, Git doesn't have to do anything, just simply move bugFix to the commit record pointed to by main
4. Merge rebase
The second way to merge branches is git rebase. Rebase is actually taking a series of commit records, "copying" them, and putting them one by one in another place
git rebase main
// 等价于 git rebase main bugFix
C3' is a copy of C3, and the two branches are developed in parallel after copying
git rebase bugFix
Switched to main. Rebase it to the bugFix branch. Since bugFix inherits from main, Git simply moves the reference of the main branch forward.
In the development community, there are many discussions about merge and rebase. Here are the advantages and disadvantages of rebase:
Advantages:
rebase makes your commit tree very clean, all commits are on one line
Disadvantages:
rebase modifies the history of the commit tree
For example, commit C1 can be rebased after C3. It looks like the work in C1 was done after C3, but it was actually done before C3.
Some developers like to preserve the commit history and thus prefer merge. While others may prefer a clean commit tree, prefer rebase
5. Separate HEAD
HEAD is a symbolic reference to the current branch. The separated HEAD is to point to a specific commit record instead of the branch name
git checkout C1 //这里的C1表示提交记录的哈希值
State before command execution: HEAD -> main -> C1
HEAD points to main, main points to C1
after execution becomes: HEAD -> C1
6. Relative references
It is inconvenient to specify the commit record by hash value, so Git introduces relative references
Use ^ to move up 1 commit record
Use ~num to move up multiple commit records, such as ~3
git checkout main^
git checkout HEAD~4
Forcibly modify the branch location, you can directly use the -f option to make the branch point to another commit
git branch -f main HEAD~3
The above command will force the main branch to point to HEAD's level 3 parent commit
A more complex example
git branch -f main C6
git checkout HEAD^
git branch -f bugFix HEAD^
7. Undo changes
Undoing changes consists of a bottom-level part (individual files or fragments in the staging area) and an upper-level part (how the change was undone). The main focus here is on the latter
git reset HEAD~1
git reset undoes changes by rolling back several commit records of branch records. After reset, the changes made by C2 are still there, but they are not added to the temporary storage area. Reset is mainly used for branches managed by itself
While it's convenient to use git reset on a local branch, this method of "rewriting history" doesn't work on the remote branch everyone uses together!
In order to undo the changes and share them with others, we need to use git revert
git revert HEAD
The new commit record C2' introduces changes -- changes that happen to undo the commit C2. That is to say, the state of C2' is the same as that of C1
8. Copy the commit record to the current branch (selection)
git cherry-pick C2 C4
Copy C2 and C4 and commit to the current main branch
9. Interactive rebase
If you want to find the desired record from a series of commit records, you can use interactive rebase, which refers to the rebase command with the parameter --interactive, abbreviated as -i if you add this option after the
command , Git will open a UI interface and list the alternative submission records that will be copied to the target branch. It will also display the hash value and submission description of each submission record. The so-called UI window is generally in a text editor (such as Vim) to open a file. A dialog box is used in the course to simulate these operations
When the rebase UI interface is open, you can do 3 things:
adjust the order of the commit records (drag and drop with the mouse)
delete the commits you don't want (done by switching the pick state, close means you don't want this Commit record)
merge commit, which allows you to merge multiple commit records into one
git rebase -i HEAD~4
Open the UI interface here to modify the 4 submissions above HEAD, delete the submission C3, and modify the order of C4 and C5
10. Label
Branches are easy to change, and most branches are temporary and changing all the time. tag can (in a way - because a tag can be deleted and recreated in another location with the same name) permanently name a particular commit as a milestone, which can then be referenced like a branch
git tag V1 C1
Create a label V1 pointing to the commit record C1. If you don't specify a commit record, Git will use the location pointed to by HEAD
recent tags
Since tags play the role of "anchor" in the code base, Git also specially designed a command to describe the anchor point (that is, the tag) closest to you, which is git describe The syntax of git describe
is :
git describe <ref>
ref can be any reference that Git recognizes as a commit record. If you don't specify it, Git will use your current location (HEAD).
It outputs something like this:
<tag>_<numCommits>_g<hash>
tag indicates the tag closest to the ref, numCommits indicates how many commit records the ref differs from the tag, and hash indicates the first few digits of the hash value of the commit record represented by the ref you give as the ref commit
record When there is a label, only the label name is output
git describe main
v1_2_gC2 //输出
git describe side
v2_1_gC4 //输出
11. Select the parent commit record
The operator ^ is the same as the ~ operator, and can also be followed by a number num
A merge submission has two parent submissions, num refers to a parent submission, and the "first" parent submission of the merge submission is selected by default
git checkout main^
By default, it will return to the first parent submission record. In the example diagram, the first parent submission record refers to the submission record directly above the merge submission record
git checkout main^2
Back on another parent commit
These operators also support chaining operations
git checkout HEAD~^2~2
12. Remote warehouse
git clone 地址
Create a local copy of the remote repository
o/main means the remote branch, where o means origin, and the remote branch has a special attribute. When you switch to the remote branch, it will automatically enter the detached HEAD state. Git does this for the reason that you cannot directly operate on these branches, you have to complete your work elsewhere, (after updating the remote branch) and then use the remote to share your work. When we get data from the remote
warehouse When the remote branch is also updated to reflect the latest remote repository
fetch
git fetch
C2 and C3 are downloaded to the local warehouse, and git fetch completes the only but very important two steps:
- Download missing commit records from the local repository from the remote repository
- Update the remote branch pointer (such as o/main)
git fetch does not change the state of your local repository. It will not update your main branch, nor will it modify the files on your disk. You can understand git fetch as a simple download operation. If the remote warehouse has multiple branches, it will download all the commit records to each remote branch
pull
When there are new commits in the remote branch, you can merge the remote branch just like merging the local branch. That is, you can execute the following commands:
git cherry-pick o/main
git rebase o/main
git merge o/main
Since the process of first grabbing updates and then merging them into local branches is very common, Git provides a special command to complete these two operations
git pull
git fetch
git merge o/merge
Downloaded C3 with fetch, then merged C2 and C3 into C4, now our main branch contains updates in the remote warehouse
and git pull is shorthand for git fetch and git merge, using git pull can replace the above two commands, similar git pull --rebase is the abbreviation of fetch and rebase
pull operation, the commit record will be downloaded to o/main first, and then merged into the local main branch
push
git push
git push uploads your changes to the remote warehouse, the remote warehouse receives C2, the main branch in the remote warehouse is also updated to point to C2, our remote branch (o/main) is also updated, and all branches are Synced
NOTE - The behavior of git push with no arguments is related to a Git configuration called push.default. Its default value depends on the version of Git you are using
In this case, git push will fail, because your latest commit C3 is based on C1 in the remote branch. And the branch in the remote warehouse has been updated to C2, so Git rejected your push request, so in actual development, you must first git pull to update to the latest before submitting
git fetch
git rebase o/main
git push
Use git fetch to update the remote branch in the local warehouse, then use rebase to move our work to the latest submission record, and finally push it to the remote warehouse with git push
git pull --rebase
git push
You can also use git pull --rebase to simplify the command
git fetch
git merge o/main
git push
Using git fetch to update the remote branch in the local warehouse, then merging the new changes into our local branch (in order to include the changes in the remote warehouse), and finally we use git push to push the work to the remote warehouse
git pull
git push
Simplify commands with git pull
13. The remote server rejects! (Remote Rejected)
If you are working in a large cooperative team, it is likely that main is locked and cannot be submitted directly to main, requiring some Pull Request process to merge changes. If you directly commit (commit) to the local main, and then try to push (push) changes, you will receive a message similar to this: !
[remote server rejected] main -> main (TF402455: Not allowed to push (push) this branch ; You must use a pull request to update this branch.)
The remote server refuses to directly push (push) to main, because the policy configuration requires pull requests to submit updates.
You should follow the process to create a new branch, push (push) this branch and apply for a pull request
git reset --hard o/main
git checkout -b feature C2
git push origin feature
Reset first to ensure that the main branch is consistent with the remote server, here use --hard hard reset, you can omit that option to avoid trouble! But to record the default in Git is --mixed
14. Remote Tracking
When you clone, Git creates a remote branch (such as o/main ) in the local repository for each branch in the remote repository. Then create a local branch that tracks the active branch in the remote repository. By default, this local branch will be named main, and main is set to track o/main - which means specifying the push destination for the main branch and The target to merge after pulling.
This also explains why you see the following output when cloning:
local branch “main” set to track remote branch “o/main”
There are two ways to set this tracking property, the first is to switch to a new branch through the remote branch, execute:
git checkout -b totallyNotMain o/main
would create a branch called totallyNotMain that tracks the remote branch o/main
git checkout -b foo o/main
git pull
Switch to a new branch named foo, let it track main in the remote warehouse, use the implicit target o/main to update the foo branch, note that main has not been updated
The second method is to use: git branch -u command, execute:
git branch -u o/main foo
This way foo will track o/main. If you are currently on the foo branch, you can also omit foo:
git branch -u o/main
15. Parameters of Git Push
Parameters can be specified for push, the syntax is:
git push <remote> <place>
git push origin main
The command is: cut to the "main" branch in the local warehouse, get all the submissions, and then find the "main" branch in the remote warehouse "origin", and add all the submission records that are not in the remote warehouse. In fact, it is to The location of the two repositories that are synchronized
git checkout C0
git push origin main
By specifying parameters, the main branch in the remote warehouse is updated
If the above git push does not specify parameters, the command will fail because the HEAD we switched to does not track any branches
When specifying the place parameter as main, we also specify the source and destination of the commit record. If the names of the source and destination branches are different, use the following command
git push origin <source>:<destination>
git push origin foo^:main
source can be any location that Git can recognize, foo^ resolves to a location, and uploads all commit records that are not included in the main branch of the remote warehouse
git push origin main:newBranch
If the target branch you want to push to does not exist, Git will help you create this branch in the remote warehouse based on the name you provided
git push origin :foo
You can also not specify the source, by passing a null value source to push, the branch in the remote warehouse will be deleted
16. Parameters of Git fetch
The place parameter of git push, and the source:destination separated by colons, these parameters can also be used for git fetch, but in the opposite direction (because it is downloading instead of uploading)
git fetch origin foo
Only the latest commit record in the foo branch in the remote warehouse is downloaded, and o/foo is updated.
Why does Git put the new commit in o/foo instead of my local foo branch? Because you probably have unfinished work on the foo branch and you don't want to mess it up
You can also specify source:destination, note: source refers to the location in the remote warehouse, and destination is the location where the submitted local warehouse is to be placed. It is just the opposite of git push, and developers rarely do it, so I won’t demonstrate it here
git fetch origin :bar
If the fetch is empty to the local, a new branch will be created locally
17. Git pull parameters
The following commands are equivalent in Git:
git pull origin foo 相当于:
git fetch origin foo
git merge o/foo
besides…
git pull origin bar~1:bugFix 相当于:
git fetch origin bar~1:bugFix
git merge bugFix
pull can also use source:destination
git pull origin main:foo
First create a branch called foo locally, download the commit record from the main branch in the remote warehouse, merge it into foo, and then merge it into our current branch bar