GNU LilyPond Contributor's Guide: 1.4 Advanced git stuff

## 1.4 Advanced git stuff

Note: This section is not necessary for normal contributors; these commands are presented for information for people interested in learning more about git.

It is possible to work with several branches on the same local Git repository; this is especially useful for translators who may have to deal with both `lilypond/translation` and a stable branch, e.g. `stable/2.12`.

Some Git commands are introduced first, then a workflow with several Git branches of LilyPond source code is presented.

### 1.4.1 Introduction to Git concepts

A bit of Git vocabulary will be explained below. The following is just introduction material; for better understanding of Git concepts, you are invited to read further documentation, especially Git Community Book at http://book.git-scm.com/.

The `git pull origin` command above is just a shortcut for this command:

>     git pull git://git.sv.gnu.org/lilypond.git/ branch:origin/branch

where `branch` is typically `master`, `web` or `lilypond/translation`; if you do not know or remember, see Getting the source code to remember which commands you issued or which source code you wanted to get.

A commit is a set of changes made to the sources; it also includes the committish of the parent commit, the name and e-mail of the author (the person who wrote the changes), the name and e-mail of the committer (the person who brings these changes into the Git repository), and a commit message.

A committish is the SHA1 checksum of a commit, a number made of 40 hexadecimal digits, which acts as the internal unique identifier for this commit. To refer to a particular revision, don’t use vague references like the (approximative) date, simply copy and paste the committish.

A branch is nothing more than a pointer to a particular commit, which is called the head of the branch; when referring to a branch, one often acutally thinks about its head and the ancestor commits of the head.

Now we will explain the two last commands you used to get the source code from Git – see Getting the source code.

>     git remote add -f -t branch -m branch origin git://git.sv.gnu.org/lilypond.git/
>     git checkout -b branch origin/branch

The `git remote` has created a branch called `origin/branch` in your local Git repository. As this branch is a copy of the remote branch web from git.sv.gnu.org LilyPond repository, it is called a remote branch, and is meant to track the changes on the branch from git.sv.gnu.org: it will be updated every time you run `git pull origin` or `git fetch origin`.

The `git checkout` command has created a branch named `branch`. At the beginning, this branch is identical to `origin/branch`, but it will differ as soon as you make changes, e.g. adding newly translated pages or editing some documentation or code source file. Whenever you pull, you merge the changes from `origin/branch` and `branch` since the last pulling. If you do not have push (i.e. “write”) access on git.sv.gnu.org, your `branch` will always differ from `origin/branch`. In this case, remember that other people working like you with the remote branch `branch` of git://git.sv.gnu.org/lilypond.git/ (called `origin/branch` on your local repository) know nothing about your own `branch`: this means that whenever you use a committish or make a patch, others expect you to take the latest commit of `origin/branch` as a reference.

Finally, please remember to read the man page of every Git command you will find in this manual in case you want to discover alternate methods or just understand how it works.

### 1.4.2 Git commands for managing several branches

#### Listing branches and remotes

You can get the exact path or URL of all remotes with running

>     git remote -v

To list Git branches on your local repositories, run

>     git branch     # list local branches only
>     git branch -r  # list remote branches
>     git branch -a  # list all branches

#### Checking out branches

To know the currently checked out branch, i.e. the branch whose source files are present in your working tree, read the first line of the output of

>     git status

The currently checked out branch is also marked with an asterisk in the output of `git branch`.

You can check out another branch `other_branch`, i.e. check out `other_branch` to the working tree, by running

>     git checkout other_branch

Note that it is possible to check out another branch while having uncommitted changes, but it is not recommended unless you know what you are doing; it is recommended to run `git status` to check this kind of issue before checking out another branch.

#### Merging branches

To merge branch `foo` into branch `bar`, i.e. to “add” all changes made in branch `foo` to branch `bar`, run

>     git checkout bar
>     git merge foo

If any conflict happens, see Resolving conflicts.

There are common usage cases for merging: as a translator, you will often want to merge `master` into `lilypond/translation`; on the other hand, the Translations meister wants to merge `lilypond/translation` into `master` whenever he has checked that `lilypond/translation` builds successfully.

### 1.4.3 Working on LilyPond sources with several branches

#### Fetching new branches from git.sv.gnu.org

To fetch and check out a new branch named `branch` on git.sv.gnu.org, run from top of the Git repository

>     git config --add remote.origin.fetch +refs/heads/branch:refs/remotes/origin/branch
>     git checkout --track -b branch origin/branch

After this, you can pull `branch` from git.sv.gnu.org with

>     git pull origin

Note that this command generally fetches all branches you added with `git remote add` (when you initialized the repository) or `git config --add`, i.e. it updates all remote branches from remote `origin`, then it merges the remote branch tracked by current branch into current branch. For example, if your current branch is `master` — which is the case if you got the sources with the commands described in Main source code and did not issue any `git checkout` command — `origin/master` will be merged into `master`.

#### Local clones, or having several working trees

If you play with several Git branches, e.g. `master`, `lilypond/translation`, `stable/2.12`), you may want to have one source and build tree for each branch; this is possible with subdirectories of your local Git repository, used as local cloned subrepositories. To create a local clone for the branch named `branch`, run

>     git checkout branch
>     git clone -l -s -n . subdir
>     cd subdir
>     git reset --hard

Note that `subdir` must be a directory name which does not already exist. In `subdir`, you can use all Git commands to browse revisions history, commit and uncommit changes; to update the cloned subrepository with changes made on the main repository, cd into `subdir` and run `git pull`; to send changes made on the subrepository back to the main repository, run `git push` from `subdir`. Note that only one branch (the currently checked out branch) is created in the subrepository by default; it is possible to have several branches in a subrepository and do usual operations (checkout, merge, create, delete...) on these branches, but this possibility is not detailed here.

When you push `branch` from `subdir` to the main repository, and `branch` is checked out in the main repository, you must save uncommitted changes (see `git stash`) and do `git reset --hard` in the main repository in order to apply pushed changes in the working tree of the main repository.

### 1.4.4 Git log

The commands above don’t only bring you the latest version of the sources, but also the full history of revisions (revisons, also called commits, are changes made to the sources), stored in the .git directory. You can browse this history with

>     git log     # only shows the logs (author, committish and commit message)
>     git log -p  # also shows diffs
>     gitk        # shows history graphically

Note: The `gitk` command may require a separate `gitk` package, available in the appropriate distribution’s repositories.

### 1.4.5 Applying git patches

Well-formed git patches should be committed with

>     git am

Patches created without `git format-patch` should be committed with

>     git apply

#### Contributor’s Guide