git workflow
A good workflow leads to a usable, in-use and useful git tree.
Get up to date
- Update the
master
branch in my local environment:
git checkout master
git pull
As master
is never changed in local, git pull
will always do a fast-forward merge.
- Update a feature branch against the remote tracking branch:
git checkout feat1
git pull --rebase
- Update a feature branch against the
origin/master
branch:
git checkout feat1
git pull --rebase origin master
You could be tempted to git merge origin/master
into your local branch creating a merge commit. This makes the graph more complex.
⚠️ Difference between merging origin/master
into a feature branch and rebasing your feature branch on the top of origin/master
C8
only exists on origin/master
so side1
and side2
, two feature branches, need to be updated before being shared with your central repository and your teammates.
side1
is a local feature branch updated with git pull --rebase
→ no new commit are created.
side2
is a local feature branch updated with git pull
→ a merge commit C9
is created.
The git tree for side1
is more straight forward than the git tree for side2
which contains complicated branching links.
Start a new branch
- From the local environment
git checkout master
git pull
git checkout -b feat1
- Push the change
git checkout feat1
git pull --rebase origin/master
git push
Clean your commits 📖
afterwards
For many reasons, you can decide to keep your commits in local and push them all at once at the end of your development. In this case you may need to rewrite some of your commit messages to clarify or clean them.
Learn to play with your bunch of commits to share beautiful branches to your teammates.
git checkout feat1
git fetch
git rebase -i origin/master
As you rewriting history, the push
command could be rejected.
--force-with-lease
is a safer alternative than --force
as it refuses to push changes if the remote branch contains commits from teammates. 📖
upstream
There is no need to clean your commits afterwards after using these commands:
git add --patch
📖
git add -p ## select the changes to be added to the next commit
git commit -m "fix: Found this issue while working on this"
git add -p ## select the other changes not added to the previous commit
git commit -m "feat: New behavior added"
git commit --amend --no-edit
📖
touch "Hello" >> README.md
git add README.md
git commit -m "doc: Introduce the project"
touch "Hello\n" >> README.md
git commit --amend --no-edit ## instead of `git commit -m "oops, new line"
git commit --fixup
📖
touch "Hello" >> README.md
git add README.md
git commit -m "doc: Introduce the project" ## create commit 7736d8e
touch "How to contribute" >> CONTRIBUTING.md
git commit -m "doc: How to contribute"
touch "Hello\n" >> README.md
git commit --fixup 7736d8e ## create a special commit
git rebase -i --autosquash ## do what is expected
Rebase vs Merge Commit
True merge is done by git merge --no-ff
while git merge --ff-only
force a rebase instead. Using git merge
without any flag make a fast-forward if possible (equivalent to git rebase
or git merge --ff-only
or create a merge commit instead (equivalent to git merge --no-ff
).
The default commit message of a merge commit is standard : "Merge branch '<branch_name>'"
. This commit message is not very useful because it does not say anything that is not visible in the git tree.
* 58361b3 (HEAD -> master) feat: Add the Login functionnality
|\
| * f8c02aa (feat/Login) doc: Add some explanation for login capabilities
| * 7333496 feat: Add login button on home screen
| * d76776c feat: Add login behavior
|/
* aff31df initial commit
* f8c02aa (HEAD -> master, feat/Login) doc: Add some explanation for login capabilities
* 7333496 feat: Add login button on home screen
* d76776c feat: Add login behavior
* aff31df initial commit
In the former example with --no-ff
the git tree shows explicitly the new functionality and the detailed work that has been done. When the second one, with --ff-only
displays a linear history without grouping the commits around a feature.
A third version is possible with a well-known behavior from git platforms (github, gitlab, bitbucket) called squash and merge. The resulting git tree will be:
* 402b615 (HEAD -> master, feat/Login) feat: Add the Login functionnality
* aff31df initial commit
There are many commands to perform exactly the same action with git.
→ git pull --no-ff origin master
is the same as git fetch origin && git merge --no-ff origin/master
.
→ git pull --rebase origin master
is the same as git fetch && git merge --ff-only origin/master
and the same as git fetch && git rebase origin/master
.