Skip to content

Using Git

ronso0 edited this page Feb 22, 2024 · 11 revisions

Using Git for Mixxx Testing and Development

Mixxx uses Git for source control. Git is a distributed version control system that allows us to keep track of how our code changes and work together on it. Our code is hosted on GitHub. This page aims to get you up to speed with the basics of Git and how to use it with our workflow on GitHub. We are intentionally glossing over a lot of finer details which are explained in other #Tutorials.

There is also a short blog post summarizing the workflow and branching model: https://neval8.wordpress.com/2013/07/07/en-typical-workflow-with-github-on-shared-project/

If you have still have questions after reading this, feel free to ask on Zulip.

Install Git

Git comes preinstalled on macOS and many GNU/Linux distributions. If not, then install the git package through your distribution's package manager. On Windows, download and install Git from git-scm.org. In addition to the command line tool, there are lots of GUI Git Clients available. Many IDEs have some integrated Git functionality or have a plugin for using Git within the IDE.

Set up Git

First, sign up for an account on GitHub. Then, go to the mixxxdj/mixxx repository and click the "Fork" button in the top right. Add an SSH key for your GitHub account (otherwise you will need to re-enter your username and password frequently). To download the Mixxx code after you have set up SSH, run this command in your shell:

git clone git@github.com:YOUR-GITHUB-USER-NAME/mixxx.git

Change to the new mixxx folder that was created by the above git clone command and run the following command to add the upstream remote:

git remote add upstream https://github.com/mixxxdj/mixxx.git

This makes it easy to interact with the upstream mixxxdj/mixxx repository on GitHub's server. Note: 'upstream' is only a recommendation. You can choose any name you like, just replace all occurences of 'upstream' in the above snippet.

To download the latest updates, go to the mixxx folder and run

git fetch upstream

That will only download the updates though. To change the files on your computer to match the latest updates, run

git checkout upstream/main

to switch to the upstream main branch.

You may get an error that says:

error: Your local changes to the following files would be overwritten by checkout:
some/file/path.h
another/file/name.cpp
Please commit your changes or stash them before you switch branches.
Aborting

This means you have local file changes that are not commited, yet. You can stash your changes for later with git add -A && git stash push -m "stash comment". Or you can discard your local changes by git reset --hard or git checkout -t -f remote/branch

Configure Git so that you push to your fork by default for new branches:

git config remote.pushDefault origin

Set up automatic code checking

To get your changes merged into Mixxx it's necessary to make sure that your code matches our code style requirements. You can make git check this automatically every time you commit your changes by using the pre-commit framework. We strongly recommend using it.

You'll need at least Python 3.6. If you have got Python2 and Python3 installed in parallel, make sure python3 is default. You can check your python version by:

python --version 

Ubuntu 20.04 (focal): Python2 is default. You can change it by installing:

sudo apt install python-is-python3

Ubuntu 22.04 (jammy): The default package python3.10 3.10.6-1/3.10.4-3 is broken. The deadsnakes PPA provides a fixed version:

sudo add-apt-repository ppa:deadsnakes/python3.10-jammy
sudo apt update
sudo apt install python3.10

Confirm / Check the default Python version by:

python --version

Than, install pre-commit (On Ubuntu 20.04 you alternatively may run sudo pip3 install pre-commit).

Then, you have to set up the hooks that will check your code every time you commit. Run these from a shell within the mixxx git repository:

pre-commit install
pre-commit install -t pre-push

It will now run relevant hooks automatically on every git commit or git push in the mixxx git repository.

If you have a problems with a particular hook, you can use the SKIP environment variable to disable hooks:

SKIP=clang-format,end-of-file-fixer git commit

This can also be used to separate logic changes and autoformatting into two subsequent commits.

Using the SKIP var is preferable to using git commit --no-verify (which also disables the checks) because it won't prevent catching other, unrelated issues.

macOS: GUI-based git clients may have issues executing pre-commit hooks.

E.g. with Atlassian Sourcetree try installing the Sourcetree command line client from the preferences, then call the following from a terminal: stree.

Test a pull request

Developers propose changes to the Mixxx code by opening "pull requests" on GitHub. The currently active pull requests are listed on the GitHub website. Testing these pull requests and providing your feedback is really helpful and a great way to start getting involved in Mixxx even if you don't know how to program.

See https://github.com/mixxxdj/mixxx/wiki/Testing#github-pull-requests for details.

Create a new branch

When you are ready to start editing the Mixxx code, create a new Git branch for your work. Git branches are a way to organize your changes into separate workspaces, which allows you to work on multiple bugs/features in parallel and independently propose them for inclusion in Mixxx whenever each one is ready. Every time you start fixing another bug or working on a new feature, create a new branch following these steps:

First, download the latest updates before you start working on new changes:

git fetch upstream

Create a new branch on your computer called 'fixing_some_bug' starting from the upstream/main branch:

git checkout -b fixing_some_bug upstream/main

If you want your changes included in a current beta release or a bugfix point release (such as 2.1.1), start your new branch from the release branch instead of the main branch, for example:

git checkout -b fixing_some_bug upstream/2.2

Doing this every time you start working on a new feature or bug fix will allow you to propose your new set of changes for inclusion in Mixxx independently of what you were working on before. If you do not do this first, when you make a pull request for inclusion in Mixxx (see below), both what you were working on before and your new changes will be included in the pull request.

Commit changes

First you need to set your name and email address. If you don't do this then your commits will not be associated with your name (or your account on GitHub) and you won't get the glory and recognition you deserve! For your commits to be associated with your GitHub account, make sure to use an email address that is associated with your GitHub account.

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Also, configure Git to use the text editor of your choice. This will be used when writing messages describing your commits:

git config --global core.editor nano

Review your changes

Running git status will show which files have changes that have not been committed. Running git diff will show a color coded diff comparing your uncommitted changes to the last commit made on that branch. #GUI Tools are helpful for this. When working on code, you may end up trying some changes that you do not end up needing. Reviewing your own code is helpful for making sure you only commit the changes that are needed.

You can tell Git to show you a diff of the changes you are about to commit inside the commit message editor window. To do that, enable verbose commits via the configuration:

git config --global commit.verbose true

Make a commit

Before committing your changes in Git, you first have to tell it what changes you want to "stage" for inclusion in the commit. You do this using the git add command. You can stage all changes, single files or even pick only a part of the changes you did to a file. Once you have staged your changes, you can use git commit.

vim src/engine/enginebuffer.h  # Change enginebuffer.h
vim src/engine/enginebuffer.cpp  # Change enginebuffer.cpp
git add src/engine/enginebuffer.h  # Stage all changes from enginebuffer.h (use TAB for autocompleting file names)
git add -p  # Show all remaining unstaged changes and pick them for inclusion individually)
git commit

Git will automatically open the editor you have configured for Git. Type your commit message, then save this file in the editor to make the commit. If you've set up automatic code checking, these will now perform checks and ask you to make changes if necessary.

Instead of using git add and git commit, you can use a GUI Git client to pick what changes to include in a commit. This is helpful for splitting a large set of changes into smaller, independent commits, which makes it easier for other developers to review your code.

Push commits

When you make a commit in Git, that commit only exists on your computer until you push it to a remote repository to share with others. To push commits to another repository, configure the branch on your computer to follow a branch in a remote repository. You can do this in one step together with your first push:

git push --set-upstream origin your_branch_name

This sets up your branch to push commits to the fork for your user on GitHub's server. Once you have run this initial command, you can push more commits on that branch by simply running git push.

Open a pull request

When you are ready to propose the commits in your branch for inclusion in Mixxx, first push your latest commits (refer to the sections above). Then, go to the upstream mixxxdj/mixxx repository on GitHub's website. If you have pushed to your fork recently, you will see a message prompting you to make a new pull request. If you see that, click it. Otherwise, click the "New pull request" button.

On the page for making a new pull request, click the link that says "compare across forks". Leave the base fork as mixxxdj/mixxx. By default, the base branch is the main branch, but if you want your changes included in a different branch, be sure to select it here. For the "head fork", select the fork for your GitHub user. Where it says "compare", select the branch on your fork that you have been working on. Write a title and description for your pull request. Scroll down to check that the changes in the pull request only include the changes you intend. When you are ready, click the "Create pull request" button.

A Mixxx team member will review and comment on your pull request. Work with your reviewer to address their comments. To add new changes to your pull request in response to review comments, add commits to the branch on your computer and push them. When you push new commits, they will automatically be included in the pull request you already have open. When the changes are approved, we will merge them into the upstream Mixxx code!

Please note that Mixxx is an entirely volunteer project, so do not expect anyone to review your code instantly. We try not to let pull requests sit without review for more than a week or two, but please leave a friendly comment on your pull request to remind us about it if you do not hear any updates for a while. If you test and review other developers' pull requests, they will likely feel more inclined to reciprocate and review yours more quickly.

To work on another bug or feature, #create a new branch.

Targeting another base branch

Sometimes you started your work from the wrong base branch. Maybe you wrote a bugfix or a controller mapping that should be merged into current stable release, but started from the main branch instead of the stable version's branch.

In these cases you need to rebase your work on the correct branch. For example, the current stable version is 2.3.0 and you want your changes to be a part of the 2.3.1 release, but you based your work on main (which will become the 2.4 release), you need to rebase onto the 2.3 branch.

To rebase your work in the fixing_some_bug branch from main onto 2.3, run:

git fetch upstream
git rebase --onto upstream/2.3 upstream/main fixing_some_bug

Since this changes commits that you already pushed to the server, you need to use the -f flag when pushing the changes to the remote repository:

git push -f origin fixing_some_bug

If you already opened a PR, you need to change its base branch.

Keeping up to date with upstream

If there have been new changes in the upstream code that you would like to include in a branch you are working on, run:

git checkout your_branch_name
git pull # a shortcut for 'git fetch upstream && git merge upstream/main'

If you want to try the latest code from upstream without any of your own changes, run:

git fetch upstream
git checkout upstream/main

Note that there is usually no need to use the origin/main branch or maintain a main branch on your computer. Only developers with write access to the mixxxdj/mixxx repository need to maintain a local main branch for occasionally pushing directly to the main branch.

Tutorials

A full guide for how to use Git is outside the scope of this article. Git is an awesome tool, but it can be confusing to learn, so we strongly suggest you have a look at one of these tutorials now that you know the basics. They are sorted according to the time needed to complete them. The first one is the shortest.

  1. git - the simple guide by Roger Dudler (in 14 languages)
  2. introduction to Git by GitHub
  3. Ry's git Tutorial
  4. Learn Git Branching
  5. Pro Git (the big manual), especially the Branching chapter

All of these tutorials are interactive and guide you with helpful graphics. Don't worry if you don't understand everything the first time.

Image from xkcd

Working on mappings and skins separately from other changes

If you are working on a mapping or skin and you want to work on other changes to Mixxx at the same time, you can have both git branches open simultaneously with git's handy worktree feature. This will let you use your mapping or skin in development while testing your other branches. If your git repository is at ~/software/mixxx, you can set this up for a controller mapping by running:

$ cd ~/software/mixxx
$ git worktree add mapping your_mapping_branch_name
$ echo mapping >> .git/info/exclude # Tell git to ignore your mapping branch when looking at ~/software/mixxx
$ ln -s ~/software/mixxx/mapping/res/controllers ~/.mixxx/controllers

Now your mapping branch is open at ~/software/mixxx/mapping. This does not have to be under ~/software/mixxx (in which case you can skip adding the directory name to .git/info/exclude). You can work on your mapping in ~/software/mixxx/mapping/res/controllers and make commits when your current directory is ~/software/mixxx/mapping or any directory under that. In ~/software/mixxx, you can work on any other changes and switch between branches without affecting your mapping branch open at ~/software/mixxx/mapping.

If you want to work on a skin, you can set up another git worktree and run mixxx with the --resourcePath option set to the res directory under that worktree.

Clone this wiki locally