Bering-uClibc 4.x - Developer Guide - Hints and Tips for using Git SCM
Hints and Tips for using Git SCM | ||
---|---|---|
Prev | Bering-uClibc 4.x - Developer Guide | Next |
Contents
- 1 Background
- 2 Overview of Git
- 3 Git Repositories for LEAF
- 4 Getting Started
- 5 More Advanced Topics
- 6 Branching
- 7 Git Command Reference for CVS Users
- 8 Further Reading
Background
The LEAF project successfully used the CVS (Concurrent Version System) Source Code Management (SCM) tool, hosted by SourceForge, for many years. Various developers suggested switching to an alternative SCM such as Subversion or Git (see in particular the email thread "Talks about versioning system" on the leaf-devel mailing list in late September 2010) but the consensus was that CVS met all the basic requirements and a change of SCM would only divert resources away from other more important tasks.
The consensus view changed in late January / early February 2011, when the SourceForge systems were compromised and CVS proved particularly difficult to restore (see the SourceForge report here). In particular, the indication was that the SourceForge-hosted CVS service would be retired.
The SourceForge-hosted Git SCM service was selected as the new SCM for Bering-uClibc 4.x early in February 2011.
Overview of Git
Git is a distributed Source Code Management tool whereas CVS is a client-server SCM tool. This means that every Git repository is a "peer" (equivalent) of every other repository. One repository, in our case the one hosted by SourceForge, is arbitrarily designated as the "main" or "central" repository, but every developer has their own local, working repository with the same capabilities as the central one.
A developer initiates their own local repository by "cloning" the master one, hosted by SourceForge.
The developer then interacts with their local repository rather than interacting directly with the central repository, and periodically synchronizes the local repository with the central one. Changes made locally are "pushed" to the central repository, whereas changes made by other developers (and "pushed" to the central repository by those other developers) are "pulled" from the central repository so as to update the local repository.
It is tempting to refer to the central repository as the "master" repository, but that would be confusing as will become clear later. The term "central" or "SourceForge-hosted" repository will be used instead.
Git Repositories for LEAF
The LEAF Project currently has three separate Git repositories:
- leaf/bering-uclibc
- This is the main, active repository for the Bering-uClibc Project. Since 2011-06-20 this holds the live source code for Bering-uClibc 4.x and is the only repository that most developers need to use.
- leaf/leaf
- This was initially (until 2011-06-20) used for Bering-uClibc 4.x development but that has now moved to leaf/bering-uclibc. The leaf/leaf repository is now reserved for general purpose LEAF items not specific to any Project,
- leaf/packages
- This separate repository is used to hold the Package
.lrp
files generated for LEAF Project Releases, to keep them out of the other repositories which are reserved for source code.
In the future it is likely that further repositories will be added. The general rule is one Git Repository for each LEAF Project.
Getting Started
Browse using GitWeb
The very first step is probably to browse the web-based interface to the SourceForge-hosted Git repository at the LEAF project GitWeb to familiarize yourself with the structure.
Tip: Click on "tree" a few times, then try "summary".
Install the Git Client
The next step is to ensure you have the Git client software installed on your build host. On Red Hat-derived Linux distributions this is accomplished with:
yum install git
Clone the SourceForge-hosted Git Repository
Next, you will want to copy ("clone") the SourceForge-hosted Git repository. The naming convention for project repository URLs is documented on the SourceForge Git page. In our case "PROJECTNAME" = "leaf" and "REPONAME" = "bering-uclibc" so the repository is accessed as:
- Read-only
- git://leaf.git.sourceforge.net/gitroot/leaf/bering-uclibc
- Read-write
- ssh://USERNAME@leaf.git.sourceforge.net/gitroot/leaf/bering-uclibc
The examples that follow assume you want read-write access and will therefore use the second (ssh) variant. Obviously you need to replace "USERNAME" with your own SourceForge username. You will be prompted to enter your SourceForge account password when using the "ssh" URL, or you can configure SSH keys as described here.
To actually create a copy of the SourceForge-hosted repository change to a suitable directory on your build host and run the following command:
git clone ssh://USERNAME@leaf.git.sourceforge.net/gitroot/leaf/bering-uclibc
Note: The "git" commands must be entered as e.g. "git clone" (argument "clone" to command "git") but you will also see references to e.g. "git-clone" in the documentation. This is because the man pages use the latter naming style (with the hyphen) and in the very early days of Git there were several independent command executables called e.g. "git-clone" rather than a single command executable called "git".
This creates a new directory "bering-uclibc" under the current directory which contains a full copy of the "bering-uclibc" repository on SourceForge. Change to this new "bering-uclibc" directory for the following steps:
cd bering-uclibc
This directory "bering-uclibc" represents the local repository which is a full Git repository in its own right, although it understands that it was derived from (and is therefore "linked" back to) the SourceForge repository.
(Actually it is the .git
directory under "bering-uclibc" which is the real Git repository.)
Note: The SourceForge repository is known by the alias "origin". That alias will be used in some of the commands.
Any git commands executed in or below the "bering-uclibc" directory operate on this repository.
Configure your User Identity
Any changes you make are identified with your user details as specified in a Git configuration file. To populate these on a "per repository" basis run the following commands:
git config user.name "Your Full Name" git config user.email "USERNAME@users.sourceforge.net"
Tip: Review the contents of file .git/config
to see where these setting are maintained and what else is in this file.
An alternative is to configure these details on a "per user" basis, which means they are instead written to file $HOME/.gitconfig
and apply to all repositories (unless overridden by a "per repository" setting). To do this, add the --global argument as shown below:
git config --global user.name "Your Full Name" git config --global user.email "USERNAME@users.sourceforge.net"
Change an Existing File
That's all of the preparation complete; now we can actually change something.
The following examples show an update to buildtool/conf/sources.cfg
.
Edit the file
First change to the directory containing the file to be modified:
cd buildtool/conf
Modify the file using your favourite text editor:
edit sources.cfg
Tell Git about the changes
When the modifications are complete you need to tell Git about them. This is accomplished using the "git add" command:
git add sources.cfg
Note: With CVS you would only "add" new files or directories. With Git you need to also need to "add" changes to existing files.
Running "git add" has the effect of adding the differences in the specified file(s) to a local "index" of pending changes which is then processed by a subsequent "git commit" transaction.
Commit the changes to the local Git repository
At this point you can review the contents of the "index" of pending changes with the following command:
git diff --cached
It is good practice to always do this before running "git commit".
Note: The "--cached" argument is required once changes have been added to the index. Before running "git add" a simple "git diff filename" will show the deltas.
Another command to show what changes are pending is:
git status
This also shows what files have been modified but not yet added to the list of changes to be processed.
Next, you need to commit the changes to your local Git repository:
git commit -m "Log message for changes"
Note: With CVS this would commit the changes directly to the shared repository on SourceForge however with Git the "commit" command only commits the changes to the local Git repository.
Publish the changes to the SourceForge-hosted Git repository
Publishing the local changes to the shared Git repository hosted on SourceForge needs a further step:
git push
Tip: All of the "git" commands take a "--dry-run" command-line parameter. This processes the command as normal but does not actually update the repository. Use this while you are learning to check what effect a command will have before running it for real.
Add a New Directory
When adding a new Package it is necessary to add a new directory (under repo/
) together with (some of) the files in that directory.
This is easier with Git than with CVS, since adding the directory automatically adds the files as well.
git add packagedir/
Note that any number of related changes can be stacked up with multiple "git add" commands before running "git commit".
This means that adding a new Package entry to sources.cfg
can be done as part of the same commit as adding the source files themselves.
Update the Local Repository with Changes from SourceForge
Other developers will be making their own changes and publishing updates to the SourceForge-hosted Git repository. Update the local repository to re-align it with the master repository using the following command:
git pull
If there are no changes this responds as follows:
Already up-to-date.
More Advanced Topics
Ignoring Generated Files
Any files generated within the Git repository will show up in a "git status" and are at risk of being accidentally added to the repository. To specify that such files should be ignored, Git checks for files called .gitignore
in each directory within the repository.
The contents of a .gitignore
file take effect on files in the same directory and in all sub-directories, and the contents are basically just filename glob patterns which specify the files to be ignored.
For example, there is a buildtool/image/.gitignore
file which specifies that any generated disk Image files (in the various sub-directories) should be excluded. The contents are:
# Exclude any generated image files *.tar.gz *.iso
Moving and Removing Files
When Removing files, or Moving them around within the repository, simply use the "git rm" and "git mv" rather than "rm" and "mv". These "git" commands do what you would expect at the file system level and also keep the Git "index" updated. The changes then need to be committed and pushed.
Tagging Releases
It is customary to "tag" each Bering-uClibc 4.x release (including Betas and Release Candidates) in the SCM. This is done by running commands like:
git tag -a 4.0-rc1 git push origin 4.0-rc1
The first command creates an unsigned "annotated" tag label for the most recent commit and the second pushes it to the SourceForge-hosted Git repository.
The tags defined for a Git repository can be listed with "git tag -l". For example:
git tag -l 4.0-beta3 4.0-rc1
Branching
Default Branch
By default, Git works with a single local branch called "master", as can be seen by running the "git branch" command with no arguments:
git branch * master
The asterisk (*) indicates that this is the "current" branch.
This local branch "master" is synchronized with the "master" branch in the "origin" repository (known as "origin/master").
Creating a Branch
A new local branch can be created very easily. For example:
git branch new-branch
creates a new local branch called "new-branch" which is based on the latest commit ("HEAD") on branch "master".
If you want the branch to refer to an older snapshot of the repository, for example the release tagged as "4.0-rc1", specify this as the "<start-point>", for example:
git branch 4.0-rc1-branch 4.0-rc1
Working with a new Branch
When a new branch is created it is not automatically made the default branch. If you run
git branch
you’ll get a list of all existing branches:
new-branch * master
In order to use the new branch you need to switch to it using "git checkout". For example:
git checkout new-branch
If you now run
git branch
you’ll see that new-branch is the active branch:
* new-branch master
So you can check the active branch with
git branch
and switch the current active branch with
git checkout branch
That way one can easily work on different branches on the local host.
Note: Alternatively, a new branch can be created using the "-b" argument to "git checkout". For example:
git checkout -b beta3-branch 4.0-beta3
in which case this new branch is automatically made the default.
Comparing Branches
Can report on the differences between the current branch and another branch using "git diff branchname". For example, assuming that a new branch has been made the current/default branch this can be compared to the master branch:
git diff master
Merging a Branch
To merge the changes made in new-branch into master, run
git merge new-branch
This also works the other way around. Say you are working on a new development in new-branch but there have been changes in master which you want to incorporate:
git merge master
Deleting a Branch
A local branch can be deleted using e.g.
git branch -d new-branch
Remote Branches
In general, all Bering-uClibc 4.x development takes place along a single trunk, with identifying labels being used to signify milestones such as "4.0-beta1" and "4.0". However, in some cases it is necessary to work on multiple developments in parallel.
Imagine that "4.1-beta1" has already been released but a serious bug is found in "4.0". The bug can be fixed in "4.1-beta2" but that might take many weeks to be formally released as "4.1" and will include a large number of other changes. One solution is to fix the bug in a release called "4.0.1" which is based on "4.0" and omits the other changes in "4.1-beta1".
The best way to handle this is to create a new branch (called e.g. "4.0-fixes") which is based on the "4.0" label. In order for this branch to be shared by all of the developers it needs to be present on the main, SourceForge-hosted Git repository. Such a branch is referred to as a remote branch. In general, each developer will create their own local branch which is set up to "track" this remote branch (a tracking branch).
Creating Remote Branches
If you want to share your local branch with other developers, you push it to the remote server.
git push -u origin 4.0-fixes:4.0-fixes
The option '-u' enables tracking of the remote branch for the branch creator.
Listing Remote Branches
Add the "-r" argument to the "git branch" command to have it show remote branches. For example:
git branch -r origin/HEAD -> origin/master origin/master origin/4.0-fixes
Tracking a Remote Branch
If the remote branch already exists, a developer can set up their own local branch to track this with a command like the following:
git branch --track 4.0-fixes origin/4.0-fixes
The "tracking" means that git pull and git push will automatically read from / write to the correct branch in the remote repository.
Confirming Remote Branch Tracking
To be certain which local branches are mapped to which remote branches, run git remote show origin. For example:
git remote show origin * remote origin Fetch URL: ssh://USERNAME@leaf.git.sourceforge.net/gitroot/leaf/bering-uclibc Push URL: ssh://USERNAME@leaf.git.sourceforge.net/gitroot/leaf/bering-uclibc HEAD branch: master Remote branches: 4.0-fixes tracked master tracked Local branches configured for 'git pull': 4.0-fixes merges with remote 4.0-fixes master merges with remote master Local refs configured for 'git push': 4.0-fixes pushes to 4.0-fixes (up to date) master pushes to master (up to date)
Deleting a Remote Branch
Just in case you want to delete the remote branch 4.0-fixes, you push "nothing" to the remote branch 4.0-fixes.
git push origin :4.0-fixes
Git Command Reference for CVS Users
For developers familiar with CVS, here are the equivalent Git commands for some basic SCM tasks:
Task | CVS Command | Git Command |
---|---|---|
Check-in a modified file | cvs commit -m "Log Message" filename | git add filename; git commit -m "Log Message"; git push |
Update local repository with changes from SourceForge | cvs update | git pull |
Further Reading
- Git project Home page and Documentation page
- gittutorial(7) Manual Page
- Git User’s Manual
- SourceForge documentation on their hosted Git service
- Version Control with Git, by Jon Loeliger. Published by O'Reilly Media, Inc. 2009. ISBN 978-0-596-52012-0.
- This is not a reference manual but it describes how Git works "under the covers" which can provide a very useful foundation to understanding the more complex features.
Prev | Up | Next |