Git rebase Rewrite your history like you want
January 2018
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
What is a Git rebase
Definition
reapply commits on top of another base tip
It’s the process of moving a branch (set of commits) to a new base commit. Rebasing is a common way to integrate upstream changes into your local repository.
Git rebase vs Git merge The reasons for Git rebasing over merging are: ● maintain a linear project history ● avoid superfluous merge commits when pulling upstream changes ● give us the opportunity to clean commits In rebase, you change your branch that’s being rebased so it looks like it was branched off a new base instead of the original. The process rewrites the commits, so you’ll end up with different commit IDs.
Git rebase vs Git merge In merge, you combine two (or more) divergent branches back into one. Pulling in upstream changes with Git merge results in a superfluous merge commit. There’s also a special kind of merge called fast-forward, done when a branch being merged is just a continuation of the branch you’re merging into.
How Git rebase works Git rebase performs the following steps: 1. Identifies each commit that is an ancestor of the current commit but not of [base]. This can be thought of as a two-step process: first, find the common ancestor of [base] and the current commit; call this the ancestor commit. Second, collect all the commits between the ancestor commit and the current commit. 2. Determines what changed for each of those commits, and puts those changes aside. 3. Sets the current head to point to [base]. 4. For each of the changes set aside, replays them one by one onto the current head and creates a new commit.
Project history: linear vs non-linear
Messed things up
Dangers of rebasing ● ● ●
●
Rebasing rewrites history. It means that a rebased head cannot be pushed to a remote server, because it does not result in a fast-forward merge You have to push --force your changes to the remote branch, which can result in a loss of information; of commits pushed previously by someone else Changing published commits could confuse someone who already knows about those commits (even PHP composer if they’re already in the composer.lock) Conflicts are resolved on a per-commit basis, one by one
Never rebase commits that have been published unless you know what you're doing
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
Git history #trueStory
Interactive rebase - Bad commit messages pick pick pick pick pick pick pick pick pick pick pick pick pick
0e9527cc6e b229ff3b52 d90067ddc6 32849b097e 1f9fa75d6b e72f7874f3 2a7957be0a 2e3e2a8456 9e643ae0de 7ae9b9c0df 3932344155 3bad2a8522 83e6fc3045
Fix validation Fix exception type Fix exception type Apply type hint to return value Apply coding standards Remove casting var Rturn redirect Remove whiteline Change the order Add space Add space Remove function change null by function to get pixel
Interactive rebase - Documentation git rebase --interactive (or -i) Make a list of the commits which are about to be rebased. Let the user edit that list before rebasing. This mode can also be used to edit/squash/split commits. The commit list format can be changed by setting the configuration option rebase.instructionFormat. A customized instruction format will automatically have the long commit hash prepended to the format. [rebase] instructionFormat = %s [%an %ar]
Interactive rebase - Options pick b94e3e34cf KTN-4900 Rename variable names for consistency [Javier Gómez 31 hours ago] pick 89dbea254f KTN-4900 Change more names for consistency [Javier Gómez 28 hours ago] # # # # # # # # # # # # # # # # # #
Rebase eb045d6eda..89dbea254f onto eb045d6eda (2 commands) Commands: p, pick = use commit r, reword = use commit, but edit the commit message e, edit = use commit, but stop for amending s, squash = use commit, but meld into previous commit f, fixup = like "squash", but discard this commit's log message x, exec = run command (the rest of the line) using shell d, drop = remove commit These lines can be re-ordered; they are executed from top to bottom. If you remove a line here THAT COMMIT WILL BE LOST. However, if you remove everything, the rebase will be aborted. Note that empty commits are commented out
git rebase --interactive master origin/master {hash}^ HEAD^ / HEAD^^^ HEAD~4 git rebase --continue --skip --abort --quit --edit-todo https://unsplash.com/photos/4u2U8EO9OzY
Interactive rebase - Remember Things to remember: ● When entering to the commit list screen after running git rebase --interactive, remove all uncommented lines to abort. ● Do not edit commit subjects on that screen, it’s useless. ● You can use git config to improve how the commit information is displayed. ● Be careful reordering commits, later changes could depend on previous ones. ● You can remove a commit squashing it with its reverted commit. But read carefully the message: --allow-empty and git reset HEAD^. ● Use git rebase --skip if you don’t want an empty commit. Occurs when the changes of the applied commit are already there.
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
Git commit with --amend - Documentation git commit --amend Replace the tip of the current branch by creating a new commit. The recorded tree is prepared as usual, and the message from the original commit is used as the starting point, instead of an empty message, when no other message is specified from the command line. The new commit has the same parents and author as the current one. You should understand the implications of rewriting history if you amend a commit that has already been published. (See the "RECOVERING FROM UPSTREAM REBASE" section in git-rebase[1].) git rebase --interactive HEAD^
edit
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
Git pull with rebase git pull --rebase[=false|true|preserve|interactive] (and --no-rebase) Can be set as the default option. When true, rebase branches on top of the fetched branch, instead of merging the default branch from the default remote when "git pull" is run. See "branch.
.rebase" for setting this on a per-branch basis. When preserve, also pass --preserve-merges along to git rebase so that locally committed merge commits will not be flattened by running git pull. NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see git-rebase[1] for details). git config --global pull.rebase true [pull] rebase = true
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
Examples ●
Simple rebase to integrate upstream master changes into a feature branch.
●
Rebase a sub-branch onto the feature branch on which we started, forcing a conflict due to rebases on the feature branch.
●
Remove merge commits using rebase.
●
Interactive rebase removing commits in between to force conflicts.
Contents ● ● ● ● ● ●
What is a rebase? Difference with merge Interactive rebase Commit --amend Pull --rebase Examples Other information
Other information
Extra things you can research and other concepts commented during the presentation: ● ● ● ● ●
git rebase with --onto parameter. Read the documentation: https://git-scm.com/docs/git-rebase git config https://git-scm.com/docs/git-config git mergetool git difftool git show
[email protected]
linkedIN/company/adsmurai Passeig de Gràcia, 60 4º 08007 Barcelona Phone: +34 931 222 301 Spain © 2018 Adsmurai all rights reserved This document is strictly private, confidential and personal to its recipients and should not be copied, distributed or reproduced in whole or in part, nor passed to any third party.
facebook/adsmurai
twitter/adsmurai
Newsletter mensual