Git Guidelines¶
Some guidelines for developers about how to work with GIT. Please read this carefully before you make any changes to the code. This is work in progress, feel free to adapt or improve, or ask somebody if something is unclear.
Git documentation¶
- General git documentation: https://git-scm.com/docs
- Git cheat sheet: https://training.github.com/
Graphical user interface¶
Git can be quite complex using a GUI can help. There are many options for an overview see https://git-scm.com/downloads/guis.
Git Guidelines for ProDiMo¶
We expect that all ProDiMo developers familiarise themselves with the basics of the GIT version control software, in particular the concept of branches, releases and the head node. For this purpose, we created a test repository https://gitlab.astro.rug.nl/prodimo/prodimogittesting where you can play around and experiment without worrying to break something (but please finish reading this page first).
For developers, who want to include new functionalities or need to change the ProDiMo code for other reasons, we recommend to create a branch, regularly commit and push the developments, do a git rebase often to keep up with the incoming changes on the remote master. The advantage is that you can then use the management tools on gitlab to see what you have done and when. Finally, if a development is finished, request a "git merge" of your branch. This will involve checks done by a code maintainer of your coding, and will eventually trigger the process of releasing a new version.
The following section describes common use cases and recommendations every ProDiMo developer should follow closely.
Initial config commands (only once)¶
The following commands should be executed before you commit anything to ProDiMo. Execute those commands within your prodimo git directory, after you cloned the repository.
git config user.name "Your Name"
git config user.email "your.email@email.com"
git config credential.helper store
git config pull.rebase true
git config pull.merge false
git config pull.ff only
git config push.default current
The first two commands set your display name on gitlab and your commit email (identification of your commits). The third command stores your password so that you do not have to enter it all the time (optional). The last chain of the commands set the default behaviour for pull requests (just copy it, it is important!) and push requests (only pushes the current branch). You can check your repository config with git config --list.
Check the status of your local repository¶
do this always, before you do any git commands. The . is optional and restricts output to the current directory
git status
Update your repository from remote¶
The default (main) branch for ProDiMo is called master. We recommend to git pull regularly and keeping the master up-to-date. We recommend doing code changes in a separate branch and when the changes are finished merge the branch into the master (see below). Note that git pull affects all folders and files in your branch! You cannot do that for selected files. The second command downloads a branch that you don't have yet in your local repository (e.g. if you want to check or work with other people's code changes).
git pull
git checkout BranchName
If git pull does not work¶
if you want to "git pull", and you get error messages, for example "error: Your local changes to the following files would be overwritten ..." you usually have modified files that are in conflict with the incoming modifications done by others on the remote repository. The next steps depend on what kind of modifications you have.
- throw away un-committed local changes
This command will throw away your local changes and re-install the version from your last commitment. If you don't need these changes any-more, restoring the old version often makes "git pull" work again (the example for a file in the directory idl).
cd idl
git restore prodimo.pro
- throw away already committed local changes
There are several scenarios and ways to get rid of commits that were not yet pushed into the repository. It depends for example how many commits you have made already. Good explanations of undo options for git can be found here:
- https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting
- https://docs.gitlab.com/topics/git/undo
A common scenario might be that you just want to throw away all your commits that have not yet been pushed to the remote. This can be done by this (be aware this cannot be undone):
git reset --hard
Resolving conflicts¶
Conflicts can happen when you merge a branch into e.g. master and somebody else made in the meanwhile changes to a file that you also changes. In that case, you have to resolve the conflict manually, meaning editing the file. git marks the potential conflicts (e.g. with >>>>>) and you have to decide what to keep and what not. Git usually provides you with instructions (read them carefully). The next paragraph describes the likely most common scenario for a conflict, but other scenarios are also possible.
You are working in a branch (can be the master) and you made changes locally with or without commit. At the same time, somebody else made changes to that branch and pushed them already. If you try then a git pull, git will indicate a conflict, also if you try git push. Again you have to resolve the conflict by hand. If you make git push and you have local uncommitted changes git asks you to commit them. If you just want to throw away your local changes see above. If you want to keep them commit them (from here on it is the same as you would have committed the changes already locally). Then do git pull again and git provides you with instructions on what to do. You most likely have to edit the conflicting file(s) and resolve the issues (usually marked with >>>> or <<<<). Commit the changes (you merged them, so there is a change) and continue with git rebase --continue (as git has told you earlier). Then the rebase/merge should have been successful, and you might want to push your changes to the remote repo.
Committing and publishing your changes¶
Note that a filename can also be a folder name. Use "git rm" (or git rm -r ) if you want to delete something. When you do a "git commit", please use a concise description for the commit message.
git commit only updates your local repository, if you want to publish the changes you also need to do a git push. However, this is optional and one can make several commits before pushing them to the remote repository. We recommend committing often and in small patches (e.g. small change, test, commit) and then push when the task is finished.
git pull
git add filename or git rm filename
git commit
git push
This will commit and push your changes from the branch you are currently working on. As already noted, code changes should be made ideally in a separate branch and not directly in the master (see below).
Working with branches¶
Create a new branch¶
If you are making changes to ProDiMo you should do that in a new branch (not the master).
First, list all branches (the * shows your active branch), then switch to master. From there your new branch starts. Make sure it is up-to-date (git pull) or that you are at the commit from where you want your branch to start (git checkout commitSHA). Create your new branch, here called experiment. Then switch to it, and now you can start working on it as usual (with git add, git commit, ... see below). Finally, use the last command to push your changes (commits) to the GitLab server, so that other people can see/use it.
git switch master
git pull
git branch experiment
git switch experiment
git branch --set-upstream-to=origin experiment
git push
Note: if you are working git a git version < 2.27.0 use git checkout experiment instead of switch.
With the last git push the current branch is pushed to the remote repo with the same name, this also happens if the branch is not yet in the remote repo, if you have set push.default=current. Otherwise, you might have to do git push -u origin experiment.
you can just switch between branches, change some files and commit - that will only affect the version of the files in that branch. If you then switch to another branch, those changes are not there. But you have to finish the process and commit before switching to another branch, otherwise, git cannot know and you just see your locally changed files in all branches!
git switch experiment
emacs filename
git add filename
git commit
git switch master
more filename
A useful command is also git stash. With this command, one can save local changes without committing them. If you are working in a branch, but need to switch to another branch, you can stash your changes and then restore them when you are done with the other branch (see Quickly save local changes).
Update your branch with changes from master (rebase)¶
If you are working within a branch on some code changes, we highly recommend rebasing your branch to the master frequently, as this simplifies the process of merging your branch into the master and also keeps the repository clean. It also has the advantage that you already have included the most recent changes from the master in your branch during the development and testing of your new code.
You can do this as follows. If you get conflicts, you need to resolve them. The push at the end is optional and only required if you want to publish your current branch.
git switch experiment
git pull
git rebase origin/master
If the rebase does not work automatically, you likely did run into a conflict (read the output of the rebase command carefully). You then have to manually resolve the conflict (edit the conflicting files). This will produce a new commit as you are merging changes, then git add and rebase --continue:
git rebase origin/master
emacs filename
git add filename
git rebase --continue
This way, filename is now in the desired state after rebase in branch experiment, but filename on branch master has not changed.
If you are uncertain, you can abort the rebase process with git rebase --abort.
After the rebase is finished check if everything looks okay (i.e. git status) and then push the changes to the remote. Often a forced push is needed because of rebase, like that:
git push -f
If you are working in a branch that is not yours, try first the push without the -f(force) option as this is more secure. However, the '-f' is recommended if you are rebasing a branch that has commits that were already pushed to the remote branch. Without the '-f' the push will not work and you would need a git pull but that can produce duplicated commits. So if you are working in your own branch the -f should be the way to go.
Merge your branch into master, then delete your branch¶
Finally, if you are happy with your code in branch experiment, you should merge it into the master, which concludes your work on experiment. The result is just one branch (master). This can only be done by users with the GitLab role "Maintainer". If you have the role "Developer" you need to push your branch to GitLab and ask somebody with "Maintainer" role to merge it (Merge request, see below) into the master. The last two commands can then be used to delete the local copy of the branch and the copy on the remote repository. Please also remove the branches from the remote repository if it is not needed any-more. The easiest way is to use the Gitlab web interface). From the command line the following commands are required.
git pull
git switch master
git merge experiment
git push
git branch -d experiment
git push origin -d experiment
Note that the git merge might not go through easily (it should if you did a rebase of your branch just before merging), but you have to resolve the conflicts as above (this time deciding how the filename looks like on master after git merge --continue), i.e. you make decisions for all users, so do this very carefully.
The last two commands delete the branch locally (you will get an error if the branch is not fully merged, then you can use -Dif you are certain), and then tells git to also delete the branch in the remote repo (then it is really gone).
If a remote branch is deleted, it does not get automatically removed from your local git. To get rid of old/delete remote branches, you can do this:
git fetch --prune
Squash all commits in a branch to a single commit¶
If you have worked a lot on your branch, it sometimes can be very advantageous to convert all your commits into a single one. For example if you have changed things forth and back, and just want to know what is different on your branch with respect to master after all your changes. This can be done with
git switch YourBranch
git reset --soft $(git merge-base master HEAD)
git commit
git push -f
You should consider doing that when you have done complex changes and are about to merge your branch, as it makes the rebase and merge much easier. Otherwise, you might need to fix the conflicts for each and every commit since you deviated from master. But be careful! Once you did this, you can't go back to a specific intermittent state in your branch.
Another problem that may occur close to merging is how to find out which are all the modified files on your branch, and in what way they are different. You can find out like this
git switch YourBranch
git diff --name-status master
git diff master filename