Continuing the article on
what to say git, so that it does what you need and before the article how to create a PR in someone else's Open Source project on GitHub, I think it would be useful to talk about what git rebase is.
I myself do not really understand this topic and do not like to use it, for the reasons stated below, so please comment, I will add as much as possible.
So git works with commits. Each commit is a set of changes. Each commit has a unique hash. When merging branches through merge:
# git merge "another_branch"
then all of the commit are saved - the comments of the commit are saved, its hash + as a rule one more artificial commit is added. Moreover, the commits can alternate with each other. This is not always convenient. Let's say your committee decided to roll back - look in the general list where your committee is, and where your company is not very pleasant. And in general - in the general history I want to see really important changes, and not “oh, I forgot to put;”. You can use rebase to merge several commits into one. Although there is a squash & commit button in the GitHub interface - this is when you create a pull request (PR) from one branch to another (usually from your working branch to the main one) and after going through all the formalities, you can click squash & commit, update the comment and your changes will appear in the main branch as a single commit.
Other options to merge several comets into oneI used to do this
# git checkout master && git pull && git branch -b <> && git merge <> --squash
Then I watched the changes in the IDE, did the pre-committee review, then comitated and pushed the server.
')
From the pros - you can all the code, all the changes look in the IDE. Sometimes it is more convenient than through the web UI, which is on GitHub.
Carefully rebase can change the hash of the commit and lead to merge conflicts, especially if several people work on one branch.
I want to write about two cases of using rebase:
- When changes are included from one branch to another, not by merge, but by rebase:
# git rebase "another_branch"
This allows your local commits to deliver after all commits that were added to the “another_branch” branch. Your comit hashes will change.
- When you can edit a few of your comets with your hands - for example, glue them together, change the comment:
# git rebase -i {HEAD~_commit_count_|commit_hash}
Note: it is worth setting up the editor that will be used by git before invoking this command. Personally, I prefer mcedit.
So, you did everything in your cozy little branch and decided to share this comit with the world, but the world only wants one comit from you. `git rebase -i` launches the editor and offers to edit the commits (the order of the commits is top-down, unlike git log). You can leave the commit as is, you can change the comment, you can stick together with the previous one. As a rule, your first committee should be left as it is, and all others should be changed to
pick "commit_hash" "comment" → fixup "commit_hash" "comment"
.
In this case, all comments that were in fixup commits will be lost and the comment from the first commit will be used. If you had expensive comments, you should use squash instead of fixup.
But if the development process was long, then most likely you had to do the merge of the main branch. And all your commits will mix up with common commits, and it will not be an easy task to glue yours with yours. Therefore, before doing `git rebase -i <>` it is worth doing `git rebase`. `git rebase` will put all your commits at the end of the list of all commits (which you can be sure of by running` git log`) and after that launch `git rebase -i <HEAD ~ Your committee> number, except for the first lines, replace → → fixup | squash} and voila - you have one commit.
If in the process of editing the `git rebits -i <>` comit, you’ve somehow messed up, then you shouldn’t press Control + C - you don’t care about exit code from the git editor. He will just take the file and do it all. Just delete or comment out all the lines in the file. git will understand that you didn't want anything.
After rebase manipulations, you will need to push with the -F option. All this is because we are
rewriting we change the history of the commits and git honestly warns us about this.
# git push -f
An example of using git rebaseAfter that I will write what I did. Given - 2 branches - master and b1. In the process of work, we made the commits:
Initial commit - master - 2fbbe67
b1.1 - b1 - 85eac43
master after b1.1 - b505f18
b1.2 - b1 - 2d7d4ea
+1 - master - 8dcef6c
The commit in master and b1 were made independently. I wrote in one list so that the order in which everything was done was clear. Here is a list of commits in each brunch:
# git checkout master && git log
8dcef6c "+1"
b505f18 "master after b1.1"
2fbbe67 "Initial commit"
# git checkout b1 && git log
2d7d4ea "b1.2"
85eac43 "b1.1"
2fbbe67 "Initial commit"
Making git merge master in b1
# git checkout b1 && git merge master && git log
5383781 "Merge branch 'master' into b1"
8dcef6c "+1"
2d7d4ea "b1.2"
b505f18 "master after b1.1"
85eac43 "b1.1"
2fbbe67 "Initial commit"
Added new synthetic commit
Now do a rebase
# git checkout b1 && git rebase master && git log
7f18e47 "b1.2"
6fb80cb "b1.1"
8dcef6c "+1"
b505f18 "master after b1.1"
2fbbe67 "Initial commit"
Please note that our local commits rose at the end of the list, the commit numbers have changed, the synthetic commit has disappeared.
And finally, we glue our comets into one
# git rebase -i HEAD~2
File was
pick 6fb80cb b1.1
pick 7f18e47 b1.2
The file became after our editing
pick 6fb80cb b1.1
fixup 7f18e47 b1.2
Happened
# git checkout b1 && git log
9062cd7 "b1.1"
8dcef6c "+1"
b505f18 "master after b1.1"
2fbbe67 "Initial commit"
So it goes