git for ICU Developers

For git & git lfs installation see the Source Code Access page.

For setup with Eclipse, Xcode, etc. see the Setup page and its subpages.


ICU development is on GitHub, in the master branch of the git repository.

In preparation for a release, we create a maintenance branch, such as maint/maint-62 for ICU 62 and its maintenance releases.

For each release we create a release tag. releases/tag/release-62-1 (GitHub project page > Releases > Tags > select one; a Release is a Tag with metadata.)

There are additional branches that you can ignore. Some are old development branches.

Also, when you edit a file directly on the GitHub source browser (for docs: API comments, or .md/.html/.txt), it creates a branch for your pull request. Make sure to delete this branch when you are done.


We do not develop directly on the main repository. Do not clone from there to commit and push back into the main repository.

Instead, use the GitHub UI (top right) to create a fork of the repository in your own GitHub account. Then clone that to your local machine. You need only one fork for all of your ICU work.


mkdir -p icu/mine/src

git clone icu/mine/src

cd icu/mine/src

You should be in the master branch of your fork's clone.

Do not do any development in your own master branch either! That would lead to messy merging with the upstream master branch.

Instead, create a new branch in your local clone for each piece of work. You need a separate branch for each pull request. More on that later.

Linux: git checkout -b mybranchname

Now you are in a new development branch in your local git repo. Confirm with git status. Change stuff. Do git status again, use git add for staging and git commit -m 'ICU-23456 what I changed' to commit, or use git commit -a -m 'ICU-23456 what I changed' if you want to commit everything that git status shows as changed.

For looking at changes, you should set up a visual diff program for use with git difftool. See the Setup: git difftool & mergetool page.

For new files: Remember to add the appropriate copyright lines. Copy from a file of the same type, and set the copyright year to the current year (that is, the year you are creating the file).

You should have a Jira ticket for each line of work. (See Submitting ICU Bugs and Feature Requests and ICU Ticket Life cycle.) You can have multiple pull requests per ticket. Each pull request needs a ticket in Accepted state.

Always prefix your commit statements with the Jira ticket number using this pattern (including the space after the number): ICU-23456 what I changed

Local commits are only on your local machine. If your local disk crashes, your changes are gone. git push your commits to your GitHub fork.

Trivial changes

For trivial changes, such as small fixes in API docs or text files, it is ok to edit the file in the GitHub GUI, in the main unicode-org/icu repository.

You still need a Jira ticket.

Once you are done editing, the GUI lets you create a branch and a commit right in the main repository. Use the usual ICU-23456 what I changed pattern for the commit message.

Pull request, review, merge as usual, see the next section.

Remember to delete your branch after merging.

Review & commit to Unicode master

When you are ready for code review, go to your GitHub page and your ICU fork.

Select your dev branch (Branch drop-down on the left, search for your branch).

Click "New pull request" next to the Branch button, or "Pull request" on the right near "Compare". Make sure it compares with unicode-org/icu master on the left and your own fork's dev branch on the right.

Prefix the title of your pull request with the Jira ticket number, same format as for a commit.

Follow the rest of the checklist in the PR template.

Set the PR assignee to your main reviewer. You may add more people as reviewers, but there is normally just one assignee. Be somewhat judicious with additional reviewers: Don't just add them because they were recommended by GitHub.

Nice to have: Optionally set the Jira ticket reviewer field for documentation. Still possible to close the ticket if the field is empty.

Watch the PR status for build failures and other issues.

A PR reviewer (at least the assignee) should look to see if the PR does what the ticket says.

Respond to review feedback. Make changes on your local machine, commit, push to your fork. The GitHub PR will update automatically for your additional commits.

You should normally squash multiple commits into one in your fork before merging.

Once the reviewer(s) has/have approved your changes:

  • If you are an ICU team member with main repo write access:
    • Merge your commits into the Unicode master.
      • We almost always want to "rebase and merge" the commits. We normally want them pre-squashed for a simple, clean change history. We rarely want to permanently keep intermediate commits.
      • (For ICU 63 we used "squash merge" but ended up with some ill-formed commit messages. "Rebase and merge" lets us review the commit messages before merging.)
    • After you click the Merge button, if you don't use "rebase and merge" (although normally you should...), make sure that the commit message includes the "ICU-23456 " prefix, and add a suffix like " (#65)" with the pull request number (if it's not there already).
      • Known limitation: We won't have the PR number in the commit message(s) when using the recommended "rebase and merge" -- unless you manually amend the commit message(s) and add it.
    • You should probably check the box for deleting your dev branch after merging.
    • Remember one branch per PR. You can create multiple branches & PRs per ticket.
    • If this was the last commit to finish work on the ticket, then go to Jira and close the ticket as Fixed.
    • You can optionally have someone (probably the same person as your PR assignee) review the ticket as well, but that's not normally necessary.
    • (We normally use ticket reviews for non-code changes, such as a non-coding task or a web site update for the User Guide etc.)
  • Otherwise:
    • The PR assignee should be an ICU team member, and they are responsible both for reviewing and for merging your PR, and then also for closing the ticket.

Merge conflicts

When someone else has made changes that conflict with yours, then you can't merge as is.

You need to update your fork's master via your local clone, rebase your local dev branch with that, resolve conflicts as you go, and force-push to your fork.

As easy as it is in GitHub to create a fork, you would think that it would be a simple button-click to update your fork's master with commits on the Unicode master. If you find a way to do this, please update this section.

Switch to your local master.

git checkout master

Pull updates from the Unicode master (rather than a vanilla git pull which pulls form your out-of-date fork), push to your fork's master.

Norbert’s version:

git pull

git push

Andy’s version:

Once per local git repo, set up an additional "remote". Something like the following, but this may be incomplete!

git remote add upstream

git pull upstream master

git push origin master

Rebase & merge. First switch back to your dev branch (without the -b option which is for creating a new branch).

git checkout mybranchname

Then rebase, which reapplies your branch changes on top of the new master commits.

git rebase master

Sometimes you need to manually resolve conflicts. Follow the instructions git prints or look for help...

If it had stopped and you are done resolving conflicts, continue rebasing.

git rebase --continue

You might get conflicts at several stages; resolve & continue until done.

When done, push to your GitHub fork. You need to force-push after rebasing.

git push -f

Update your fork

Once in a while, you should update your fork's master with changes from the Unicode master, so that you don't fall too far behind and your new changes don't create unnecessary merge conflicts.

Go to your local master, pull commits from the Unicode master, and push to your GitHub fork. See the "Merge conflicts" section above for details. If you don't have a current dev branch, you can skip the rebasing.

Cherry-Pick to Maintenance Branch

Follow these steps for adding a commit to a maintenance branch.

First, get your commit reviewed, approved, and merged into Unicode master (see above).

Then, update your local master from the Unicode master (see above). Otherwise your git workspace won't recognize the commits you are trying to cherry-pick.

Make a note of the SHA hash/ID of your commit on the  master branch. You will use this later when cherry-picking into the maint branch.
  • The commit ID is listed on the pull request page.
  • You can use  git log  to see the SHA once your change is on master.
  • You can look at the commit history on GitHub too.
Next, checkout the maintenance branch locally.  For example, for the ICU 63 maintenance branch:

git fetch upstream maint/maint-63
git checkout maint/maint-63

Next, make a local branch off of the maint branch. This new branch will be used for your cherry-pick.

For example, to use the branch name "ICU-12345-maint-63", you can do:

git checkout -b ICU-12345-maint-63

Next, cherry-pick the commit(s) you want to apply to the maintenance branch.  Please use the -x option, which records in the commit message the original commit sha!

(Note: If you only have one commit to merge to the  maint  branch then you would only have one command below).

git cherry-pick -x 7d99ba4
git cherry-pick -x e578f3f

This creates new commits directly onto your local branch.

Look at the output from each of these commands to double-check that you got the intended commits.

Finally, push your branch to your fork (should be "origin"), and open a PR into the Unicode ICU branch maint/maint-63.

git push -u your-fork ICU-12345-maint-63

The reviewer of the PR has the following special responsibilities:
  1. Don't approve the PR unless ICU-TC has agreed that this should be a maintenance fix.
  2. Make sure that the PR is targeting the correct branch in the Unicode ICU repro. (ex:  maint/maint-63 ).
  3. Make sure that the PR includes all commits associated with the fix, which was already approved for master.
  4. Make sure that the original SHA is recorded in the commit messages (this is what -x does).
  5. Use "Rebase and merge".