Table of Contents
Clone Odoo
git clone git@github.com:odoo/odoo.git
cd odoo
Add odoo-dev (odoo's developper repository) remote
git remote add dev git@github.com:odoo-dev/odoo.git
List remotes
git remote -v
To switch of branch
git checkout [branch]
To create a new local branch
git checkout -b [version-title-trigram]
To push your local development branch to the development remote
git push -u dev [version-title-trigram]
the -u will set the remote to odoo-dev/odoo for this local branch forever,
so from this point you no longer need to precise the remote, you can simply use git push.
To check the status
git status
To check your unstaged local diff
git diff
To stage the changes of a file, to be committed
git add [file/path/to/add]
To partially stage changes to be committed. You will be prompted to tell, for each change, if you want to stage it or not.
git add -p
To check your staged local diff
git diff --cached
To unstage the changes of a file
git reset [file/path/to/reset]
To unstage partially your changes to be committed. You will be prompted to tell, for each change, if you want to stage it or not.
git reset -p
To remove the changes of a file
git checkout [file/path/to/reset]
To remove the changes partially .You will be prompted to tell, for each change, if you want to discard it or not.
git checkout -p
To remove all changes
git checkout .
To remove your current changes, but recover it later. For example if you suddenly want to work on something totally else, without loosing your previous changes. This stash the whole diff
git stash
To stash the changes of a file:
git stash [file/path/to/stash]
To stash partially the changes. You will be prompted to tell, for each change, if you want to stash it or not.
git stash -p
To unstash the last stashed changes
git stash pop
To show the changes of the latest stash, without applying it:
git stash show -p
To drop the latest stash:
git stash drop
List the stashes:
git stash list
To show the changes of a specific stash:
git stash show -p [index]
To apply the changes of a specific stash:
git stash pop [index]
To drop a specific stash:
git stash drop [index]
To commit the changes
git commit
To push the commit on the remote for the current branch
git push
To check the diff of your latest commit + your local diff
git diff HEAD^
You can add multiple ^, which stands for the number of commits.
To quickly add an additional changes to your previous commit:
git add -p
git commit --amend
git push -f
The -f in git push -f stands for "force".
BE CAREFUL
It will push your changes without checking your are up-to-date with the latest changes on the remote.
To only use in your own development branches, if you are 100% of what you do.
If you do this on a branch shared with other developers, make sure you are up-to-date with the revisions of the other developers. Otherwise you might overwrite their changes.
Stable branches in odoo/odoo, odoo/enterprise are protected. You cannot push force on them.
To remove your commit, but keep its changes
git reset HEAD^
You can add multiple ^, which stands for the number of commits you want to remove
To remove your commit, without keeping the changes
git reset HEAD^ --hard
You can add multiple ^, which stands for the number of commits you want to remove
To push your branch with the latest commit removed.
git push -f
To move a file,
git mv current/path new/path
When you move a file to another folder, or rename a file, it's best to use the above. If you simply use linux's mv,
git will detect the move as a deletion/addition rather than a path renaming.
To remove a file from a branch
git rm path/to/remove
To rebase your branch on master (to apply revisions that were added to master after you created your branch)
git checkout master
git fetch && git rebase
git checkout master-title-trigram
git rebase master
When you rebase your branch, if you have a local diff, git might tell you you have to stash or commit your changes. If you want to keep these changes, you can either:
- stash your changes before doing the above, then unstash after its done:
git stash
...
git stash pop
- add
--autostashto every above steps. This will stash and unstash your changes automatically
To "merge" your branch in another branch
(You won't use this that much at Odoo because you will use the "Merge Bot" to merge your changes)
We rarely use the git merge to avoid the "merge commit". Instead, we rebase and fast-forward.
git checkout master # switch to the master branch
git fetch && git rebase # update master to the latest commit
git checkout master-title-trigram # switch to your development branch
git rebase master # add the latest commits of master to your development branch
git checkout master # switch to the master branch
git rebase master-title-trigram # add your changes to the master branch
git push
As said, you won't do that yourself that much at Odoo, because we use pull requests and the "Merge Bot" to merge changes in stable/master branches https://github.com/odoo/odoo/wiki/Mergebot
Alternative to quickly create a remote branch from a local diff:
# write changes in files
git add -p
git commit
git push odoo-dev HEAD:master-title-trigram
git reset HEAD^ --hard
To read the commit logs
git log
To rework your 5 previous commits
git rebase -i HEAD^^^^^
# 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
# b, break = stop here (continue rebase later with 'git rebase --continue')
# 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>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
Worktrees
If you switch of branches really often, and waste precious time for the git checkout to complete,
you might consider the use of the worktrees.
Using worktrees, you have the possibility to checkout branches in different folders, while they share the same .git
directory. Considering the .git directory of odoo/odoo currently weights 3.0GB,
it's not such a bad idea to share it.
When you want to work on another branch, you just have to switch of folder, using cd.
To use worktree, you need a clone of the odoo repository:
git clone git@github.com:odoo/odoo.git master
cd master
git checkout master
Do not use -b master to directly clone the branch master.
Otherwise your repository clone won't know the references of the other branches.
Then, to setup a worktree for the branch 13.0:
git worktree add ../13.0 13.0
../13.0 is the folder where you want the branch,
13.0 is the branch for which you want a worktree.
This is an example of worktree structure. This is the structure used on our production servers.
src
├── enterprise
│ ├── 11.0
│ ├── 12.0
│ ├── 13.0
│ ├── master
│ ├── saas-12.2
│ └── saas-12.3
├── odoo
│ ├── 11.0
│ ├── 12.0
│ ├── 13.0
│ ├── master
│ ├── saas-12.2
│ └── saas-12.3
└── themes
├── 11.0
├── 12.0
├── 13.0
├── master
├── saas-12.2
└── saas-12.3
Then, to launch an Odoo server using that structure, you can use:
odoo/13.0/odoo-bin --addons-path=odoo/13.0/addons,enterprise/13.0,themes/13.0 -d mydb
Bisecting
You noticed a behavior which you consider wrong, and you want to know which commit introduced it.
To search the guilty commit:
git bisect start [bad revision] [good revision]
Example:
For the sake of the example, we will checkout a specific revision of Odoo:
git reset 5855bd11546b8f316fd20078a08b3bf7a18d7950 --hard
You noticed that recently, the company_id of the users's partner_id is no longer set on creation, while it was the case before. And you consider not having a default company_id by default a bad thing.
You can start the bisecting using:
git bisect start HEAD b0008be7d0b846eeaf71ef8f3dba7590d9d3eb6a
HEADis the current/latest revision. You could replace it with a commit hash. It's the bad revision.b0008be7d0b846eeaf71ef8f3dba7590d9d3eb6ais a revision with which you know the behavior was the one you expect. It's the good revision.
The bisecting begins:
$ git bisect start HEAD b0008be7d0b846eeaf71ef8f3dba7590d9d3eb6a
Bisecting: 17 revisions left to test after this (roughly 4 steps)
[ad5038ac74081d2dc31c3b777481402bbb2af682] [FIX] base: fix various issue of the contacts form view
git is now waiting for your input, to tell if the revision git chose has the bad behavior or the good behavior.
To test the behavior, you can either:
- launch the Odoo server, and test the behavior in the web interface,
- launch the Odoo shell, and test the behavior in the shell.
We will use the second option for this example:
./odoo-bin shell -d master
In [1]: env['res.users'].create({'login': 'test', 'name': 'test'}).partner_id.company_id
Out[1]: res.company(1,)
This is the behavior you expect. Let's tell that to git:
git bisect good
git now suggests you a new revision:
Bisecting: 8 revisions left to test after this (roughly 3 steps)
[4d37071213b6112b4ce423026c5af1ee81d5d193] [FIX] web: review domain for assets attachement
Let's test the behavior with this revision. You have to restart Odoo to reload the Python code.
./odoo-bin shell -d master
In [1]: env['res.users'].create({'login': 'test', 'name': 'test'}).partner_id.company_id
Out[1]: res.company()
This is now the behavior you do not want. Let's tell this to git:
git bisect bad
git suggests another revision:
Bisecting: 4 revisions left to test after this (roughly 2 steps)
[35e66df3e266695bcd2645cfbda7e8bd94e5a583] [IMP] * : generic improvements
You will have to repeat these steps a few times:
$ git bisect good
Bisecting: 2 revisions left to test after this (roughly 1 step)
[1d135ffc061ab6c8c607c476599d4a18607d5d8b] [FW][FIX] base: No company_id on new res.partner
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[b6553afeacbb76e46152b25fb09fe369751477ba] [FIX] base: properly alert the user of bundle compilation errors
$ git bisect good
Until git tells you the guilty revision:
1d135ffc061ab6c8c607c476599d4a18607d5d8b is the first bad commit
commit 1d135ffc061ab6c8c607c476599d4a18607d5d8b
Author: fw-bot <otis@odoo.com>
Date: Thu Feb 27 13:51:26 2020 +0000
[FW][FIX] base: No company_id on new res.partner
When a user is created, its partner_id shall not have any company_id.
A test has been added to check that in 'base/test'.
Update test_mail tests by setting a company to partner_id linked to users
as now, by default the partner linked to a new user has no company_id.
closes odoo/odoo#46515
Task: 2198688
Forward-port-of: #45900
X-original-commit: 187b12fc5715721efdd9af283e086dfc3f856fc2
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
And you can now notice that, not having a company_id on the partner_id of a newly created user is actually the desired behavior, despite what you were thinking.
To stop the bisecting:
git bisect reset
Pull request flow
At Odoo, we use a rebase flow. This means that when you want your feature branch to be up-to-date compared to master, you will do a rebase instead of a merge. E.g. if you began working one week ago on some feature but you want to have the latest changes of master in your feature branch, simply do:
git fetch origin
git checkout my-feature-branch
git rebase origin/master
Once a review has been done on your branch on Github, you will probably need to do some changes. Since the history of your branch should be clean to be ready for merge, this means that you will need to modify your history so that what you include for your review is part of a previous commit. For that, you can use the interactive rebase and fixup commits.
Fixup commits are a simple way to prepare a future rebase. Let's imagine that I have a branch with 2 commits:
git log -n 2 --oneline
9714ff3b47c (HEAD -> master-my-branch dev/master-my-branch) [IMP] crm: change the way it works
d0794f18827 [IMP] base: change something for res.partner
As part of the review, modifications to the code changes I did in both commit are required. To make this easy, avoid doing all the edits in one go - split the changes by knowing in advance which will go in which commit:
git add . -p # add the stuff you need in the staging for the first commit
git commit --fixup=d0794f18827 # the hash of the commit these changes will be merged into
git add . -p # add the stuff you need in the staging for the second commit
git commit --fixup=9714ff3b47c
This will create commits with a name structure that git can recognize in the next step to make your life easier. Indeed, once all your fixup commits are ready, you can do an interactive rebase:
git rebase origin/master -i
This will open your text editor with the list of commits to apply, the order in which they will be applied and an operation to do on them. You can squash commits (merge a commit in the previous one and merging their commit messages), fixup commit (same but without merging descriptions - it preserves the description of the first commit only), remove commits, reword commits (change the message but not the changes) or edit them entirely (in that case the rebase stops at that commit and let you do your changes until you tell git to continue the rebase).
The real nice thing with using the --fixup argument is that the commit message tells git that you want a commit to be fixed up in another one. In that case, you can let git re-order everything for you automatically:
git rebase origin/master -i --autosquash
The --autosquash command will make git re-order everything and fix up the 'fixup' commits in the one they belong to. This doesn't prevent rebase conflicts, but it makes rewriting history a tad easier.
Once your rebase with your review changes is done, you can then push on the remote so that the PR is up-to-date.
