- Make sure you have configured git tools: see configuring tools.
- Make sure you have updated git aliases: see GIT ALIAS.
Performing a daily rebase is good, in order to be up-to-date with the changes in the integration branch.
WHY? Because you integrate the progress of the base branch into YOUR branch, so that you will have fewer conflicts to resolve, and the rebase process will take less commits to apply when rebasing against your branch.
💡 TIP You can rebase your current branch against the remote branch by using the alias
rebasebr
git rebasebr main
The sooner you REBASE your branch, the fewer conflicts to resolve.
Do not rebase against multiple branches. Try to have only one integration branch.
This way we will keep an eye only in one branch, for example, main
as your default integration branch.
AVOID as much as possible mutate stable branches such as
main
, DO NOT rebase main
against another branch, and DO NOT perform an interactive rebase on main
.
Remember that the git rebase
command rewrites the branch’s history (SHAs).
That is becasuse when performing a rebase
or rebase -i
, you can reorder,
edit, merge, or delete commits, hence the identity (SHA) of each commit affected will change.
- Let's say this is the last commit on
main
:6ace7bf4 [US-703] Fixed bug #12 on MultiSelect component
, - Then we perform an interactive rebase to merge old commits:
git rebase -i HEAD~4
. - The history on
main
has changed, and the last commit has a new SHA:c18b70b2 [US-703] Fixed bug #12 on MultiSelect component
.
After reordering or merging commits, the identity of the subsequent commits
will change, giving them a new SHA. That means that my local branch main
has
diverged from the remote branch main
. So to upload my changes to the server we
will have to force the push: git push --force-with-lease origin main
. But this
is a BAD PRACTICE, because usually main
is protected, but also, performing a
forced-push on main
will affect to all team members. Basically the SHAs on my
mutated main
are different from the other guys, not because there are new
commits, but because the existing commits have a different SHA.
💡 IMPORTANT
If you have to deal with that problem, you can use the powerful
rebase --onto
.
You can rebase a part of a branch using a specific commit in your branch as the starting point to rebase against another branch (or SHA).
The syntax for Git command is:
git rebase [--onto <new-base>] [<old-base> [<target-branch>]]
In our previous case, after the main
branch was mutated, we can run
git rebase --onto
by specifying the new-base (main
) and the old-base
commit (starting point) in our target-branch.
# current branch: feat-x
# get latests changes of remote main
git fetch origin main
# look for the old-base SHA commit
git log --oneline
# 6ace7bf4 is the last commit (old-base) not belonging to my branch feat-x
# git rebase [--onto <new-base>] [<old-base> [<target-branch>]]
git rebase --onto origin/main 6ace7bf4 feat-x
With the above command we are telling to git rebase --onto
to apply
origin/main
as the new-base and replace the old-base SHA,
to finally update the target-branch feat-x
with the new history line.
💡 TIP The previous command can be achieve using the alias
rebaseonto
git rebaseonto origin/main 6ace7bf4
🔍️ Read more about
rebase --onto
:
The git rebase -i
help us to reorganize commits in our branch.
The following are the possible actions you can perform:
# 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
# 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>]
Let's assume these are the commits in our branch, where {1}
represents
the oldest commit, and {4}
represents the most recent commit.
{1} sha-0b2-1 [US-753] Fixed issue #16 on Linear component
{2} sha-9fa-2 753 WIP
{3} sha-774-3 753 WIP 2
{4} sha-bb0-4 [US-703] Fixed bug #12 on MultiSelect component
The alias git rebaseii X
allows you to edit the last X
commits,
so that we can reorganize commits in our branch, modify messages,
remove, reorder or meld commits. This also is a GOOD PRACTICE before
a PR, to reduce noise and facilitate code review.
# us-753 is our current branch.
# Rebase the last 4 commits.
$ git rebaseii 4
The editor will show the prompt with the commands for the last 4 commits:
pick sha-0b2-1 [US-753] Fixed issue #16 on Linear component
fixup sha-9fa-2 753 WIP
fixup sha-774-3 753 WIP 2
pick sha-bb0-4 [US-703] Fixed bug #12 on MultiSelect component
# 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
# 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>]
In this scenario we are going to "fixup" (meld) the two WIP...
commits into
the predescessor commit, that is to meld 753 WIP 2
and 753 WIP
into
[US-753] Fixed issue #16 on Linear component
.
After saving changes, our new log will be:
c18b70b2 [US-753] Fixed issue #16 on Linear component
6ace7774 [US-703] Fixed bug #12 on MultiSelect component
🔍️ Read more about rewriting-history:
All git alias
used in this document assumes main
as the default integration branch.
See git-alias.sh, git-alias.ini and
NEW ALIAS.
You can register the aliases in two ways:
- Run git-alias.sh:
sudo chmod +x git-alias.sh
thenbash git-alias.sh
- Open a terminal and run:
code ~/.gitconfig
orgit config --global -e
, and paste the content of git-alias.ini into the[alias]
placeholder.
Creates a new branch starting from the current branch.
First, check for updates in the current branch, then apply updates,
and finally creates the new branch and check out to it.
# Alias:
# git pull origin <current-branch> --rebase && git checkout -b <new-branch>
$ git newbr new-branch
Why use lowercase when naming branches?
Because it reduces errors in the file system when dealing with different platforms.
Linux is case-sensitive for file names, while Windows is not.
When you create a branch, git internally creates a folder for that branch.
A folder named us-753
is not the same as US-753
in a linux server, but for Windows
it is the same. Just avoid headaches.
Removes a branch from your local and remote.
# Alias:
# git branch -D <branch-name>; git push origin --delete <branch-name>
$ git rmbr branch-name
Gets the name of your current working branch.
Useful for creating other scripts.
# Alias:
# git branch | grep \* | cut -d " " -f2
$ git currentbr
Update references from remote branches and prints the list of remote branches.
HEAD
and main
are not listed.
# Alias:
# git remote update origin --prune && git branch --remote
$ git syncbr
Adds all untracked and unstaged files, and creates a new commit with a message.
# Alias:
# git add -A && git commit -a -m "message"
$ git commitall "[US-741] My commit message"
Append all untracked and unstaged files to the last commit. No message is added. The SHA of the last commit is modified.
# Alias:
# git add -A && git commit -a --amend --no-edit
$ git amend
Pushes the current branch to the server with the --force-with-lease
flag,
to check changes in remote and perform a force-push of your branch,
useful when the git amend
alias is used.
# Alias:
# git push --force-with-lease origin <current-branch>
$ git pushf
Commit and push changes
A basic example to commit changes:
# creates a new commit message including all changes
$ git commitall "[US-753] New commit"
# add new changes to the last commit
$ git amend
$ git pushf
Performs a rebase of the current branch against the remote branch. Gets the latest changes on my remote branch and synchronize it with my local branch.
# Alias:
# git pull origin <current-branch> --rebase
$ git pullbr
Reset an specific local branch whith the remote branch.
# Alias:
# git checkout <branch> && git fetch origin <branch> && git reset --hard origin/<branch>
$ git resetbr main
Performs an interactive rebase on your local branch. See the INTERACTIVE REBASE section.
# Alias:
# git rebase -i HEAD~<max-commits>
$ git rebaseii 5
Performs a rebase against another remote branch.
# Alias:
# git fetch origin <branch> && git rebase origin/<branch>
$ git rebasebr main
Peforms a rebase against another branch changing the old-base SHA.
Useful when the target branch has been mutated.
See the REBASE ONTO section.
# Alias:
# git rebase --onto <branch> <old-base-SHA> <current-branch>
$ git rebaseonto main 6ace7bf4
$ git rebaseonto integration 6ace7bf4
- Checkout to the target branch and update it from remote
- Merges your feature branch into the target branch
- Push the target branch to the server
- Delete the merged branch from both, local and server
# Alias:
# git resetbr main && git mergebr <feature-branch> && git rmbr <feature-branch>
$ git mergeto main
Let's assume our current branch is feat-x
, so for the previous command
we update the local main
branch with the latest remote changes, then merge
the feat-x
branch into main
, and finally we remove the feat-x
branch.
Merges an specific branch into the destination branch.
For the next example, we are going to merge the feat-x
branch
into main
. This alias is similar to mergeto
except that mergebr
does not remove the merged branch.
- Checkout to the target branch and update it from remote
- Merge the feature branch into the target branch
- Push the target branch to the server
# Alias:
# git checkout main && git pullbr && git merge feat-x && git push origin main
$ git mergebr feat-x main
Merges feat-y
branch into the default main
branch.
# Alias:
# git checkout main && git pullbr && git merge feat-y && git push origin main
$ git mergebr feat-y
Removes all merged branches into the target branch.
- Checkout to the target branch and update it from remote
- List all merged branches into the target branch
- Removes the merged branches
This method is destructive. Do not use it unless you know what you are doing!
# Alias:
# git checkout <branch> && git branch --remote --merged <branch> | xargs git rmbr
$ git cleanmerged main
Temporarily untrack changes in a specific file, so it will be excluded from commits.
# Alias:
# git update-index --assume-unchanged <path>
$ git untrack path/to/file
Track changes again from an untracked file, so it will be included in commits.
# Alias:
# git update-index --no-assume-unchanged <path>
$ git track path/to/file
Show structured info about commits in one-line format: sha date message author refs
By default the last 10 commits are listed, but you can pass an argument with the number
of commits to display.
# Alias:
# git log --graph --abbrev-commit --decorate --date=short --format=format:"custom-format" -10
$ git logn
$ git logn 20
List all commits in the current branch authored by an specific user, starting from a given date (yyyy-MM-dd).
# Alias:
# git log --pretty="custom-format" --date=short --author=david.rivera --since=2018-10-01
$ git logauthor david.rivera 2018-10-01
List all commits in the current branch authored by an specific user, between a given date range (yyyy-MM-dd).
# Alias:
# git log --pretty="custom-format" --date=short --author=david.rivera --since=2018-10-01 --until=2018-11-01
$ git logauthor david.rivera 2018-10-01 --until=2018-11-01
Show commits in all local branches authored by an specific user, starting from a given date (yyyy-MM-dd).
# Alias:
# git log --pretty="custom-format" --date=short --author=david.rivera --since=2018-10-01 --all
$ git logauthor david.rivera 2018-10-01 --all
List all commits in the current branch authored by an specific user that modified a specific file, starting from a given date (yyyy-MM-dd).
# Alias:
# git log --pretty="custom-format" --date=short --author=david.rivera --since=2018-10-01 --follow -- path/to/file
$ git logauthor david.rivera 2018-12-01 --follow -- path/to/file
🔍️ Learn more about
pretty-format
at https://git-scm.com/docs/pretty-formats.