Skip to main content

Tips For Using Git

About

This page is a collection of tips for how to begin as a Developer working on FreeSWITCH.

FreeSWITCH source code is now hosted at GitHub.

Click to expand Table of Contents

Sources

Hosted at SignalWire GitHub:

FreeSWITCH Master

Hosted at FreesWITCH GitHub:

FreeSWITCH Sounds

FreeSWITCH Contributions

Sofia SIP Library

SpanDSP Library

XKCD

Git: http://xkcd.com/1597/

Install Git

Developers must first install git

Our https now requires TLS1.2. If your distro does not support this, please report this problem to them. As an alternative you can use ssh to check out packages and code with a JIRA account.

Initial Checkout

You can get the latest code by changing to your working source code directory, then:

git clone https://github.com/signalwire/freeswitch.git

If you only want to obtain a specific branch use:

git clone https://github.com/signalwire/freeswitch.git
git checkout the-branch

or more simply:

 git clone -b the-branch https://github.com/signalwire/freeswitch.git

The contrib area can be downloaded with:

 git clone https://github.com/freeswitch/freeswitch-contrib.git

Checkout setup

After you check out the code, git can be configured for the FreeSWITCH project:

cd /usr/src/freeswitch
scripts/setup-git.sh

Syncing with Trunk

As the main trunk is undergoing lots of changes, you may from time to time want to pull changes from trunk into your local copy. This can allow you to pull in bug fixes, feature enhancements, etc. This is important in making certain that any of your changes remain compatible with the main trunk.

git stash
git pull
git stash apply

Delete Pulled Branch

To delete your local branch just switch back to master and then delete the topic branch:

Delete and Revert to Master

git checkout master
git branch -D username-topic_branch_name

Push to Master

If you like the changes you can merge them to your local master branch and then push them your remote repository:

Keep Change Branch

git checkout master
git merge username-topic_branch_name
git push origin master
git branch -d username-topic_branch_name

Github Workflow

  • Create a fork of github.com/signalwire/freeswitch to be able to contribute pull requests.
  • Create a feature branch for each new feature
  • Submit pull request when feature is completed and tested

Github has put a nice website up around the pull request workflow that makes it very simple for a contributor to initiate the request, and for others to see the changes that have been made, and make comments on those changes without ever having to pull the changes to their local repository.

There are a few shortcuts you can take if the user has sent a pull request via Github. The pull request URL itself can be used to obtain a patch and apply it to your local master branch and push the changes with two easy commands. If the pull request URL is [https://github.com/FreeSWITCH/FreeSWITCH/pull/2](https://github.com/FreeSWITCH/FreeSWITCH/pull/2) simply append .patch to the URL to get a patch file. We can use curl to grab the patch and push it directly into our local repository with the git am command.

curl https://github.com/signalwire/freeswitch/pull/2.patch | git am
git push origin master

Committing Changes

Add your changes to your staging area:

git add src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
git add conf/autoload_configs/unimrcp.conf.xml

Diff your changes with your local repository:

 git diff

Commit the changes in your staging area to your local repository:

 git commit -m "w00t, git commit!"

Diff your changes with the remote repository:

 git diff origin/HEAD

Push changes to the remote repository

 git push -u origin feature-branch

Git Bisect - Tracking Down Breaks and Bugs Extremely Rapidly With git

If something was working or behaving correctly before, but is not any more git has a great tool called bisect which can help find the issue with a binary tree search to find where it broke.

The syntax is:

git bisect usage

git bisect start [bad_commit] [good_commit] -- [path1] [path2] ... 

Where bad_commit is a commit that is known to be bad (i.e. HEAD) and good_commit is a commit that was known to work. Optionally, you can specify only a specific sub path (i.e. lib/) where it broke and then it will only look at commits that affected that path or other paths. Here's an example of finding something that broke within the last 10 commits:

git bisect begin

git bisect start HEAD HEAD~10

Once you do that you are now in bisect mode. You want to compile and test to try to reproduce the bug. Once you know if that version works or not just tell git with:

git bisect good or bad

git bisect bad 
or
git bisect good

then it will move on to the next commit for you to test. If you cannot figure out if it was bad or good use 'git bisect skip' to move on to the next commit. Once it figures out what commit (or commits) would be possible to blame it will let you know. The great part is that it is far quicker than trying to do it by hand. Let's say in a worst case scenario you only know it worked 6 months ago and now its broken and there are 1000 commits in between then and now. You would in the worst case only have to test 11 different builds.

When you are done you can use:

Resume Normal Work

git bisect reset

to reset back to where you were.

In addition git bisect can find the place that it first broke on its own. If you have a script that can return if it works or doesn't work you can use:

Automate git bisect

git bisect run [my_script] [arguments]

Note that the script (my_script in the above example) should exit with code 0 if the current source code is good, and exit with a code between 1 and 127 (inclusive), except 125, if the current source code is bad.

Then you do not need to do any testing by yourself just let git find the problem commit. Once you know the problem commit there is a far higher chance your bug report will be handled faster when you can tell the developers exactly where to work.

If You Change Code You Must Branch with Git

Git is not like most other source control systems: branching is actually so easy that the recommended method of making feature changes is generally to branch. Branching allows you to make changes and commit them locally even though you most likely cannot commit them directly to FreeSWITCH Master. This also allows you more easily to preserve your changes as you upgrade FreeSWITCH. If you branch for each feature or fix you try to add to FreeSWITCH it makes submitting and updating patches far easier. Branching takes two seconds. Just run:

git branch [branch_name] [source_branch] 

so for example:

git branch codec_g729_windows master 

will create a new branch from master for your work. You can switch to a branch by doing:

git checkout [branch_name] 

So git checkout master will change you back to master or git checkout codec_g729_windows will change to your branch. You do not need to commit your changes before changing branches, it will save your place automatically. To update a branch after you do a git pull on master you would run:

git merge master 

In your branch, most of the time git will figure out the proper merging for you without intervention.

Checking Out Previous Revisions

To list commits cd to where you have cloned the git repo and type:

git log 

Then to switch to that commit do:

git checkout ac59a2a1d67aca74895ceddbc709a467c572144b
make && make install

then, if you want to go back to the master:

git checkout master
git pull
make current

Note that if the revision you are trying to switch to is newer than your clone then you will need to first bring your clone up to date:

git pull 

Cleaning Out Previous Revisions

git clean -fdx

Michal Bielicki: that will kill everything that is not from the current git

When making large jumps between revisions you'll need to clean your old libs and mods to avoid errors like this:

Making all in .

make[2]: Entering directory `/usr/local/src/freeswitch'
CC src/freeswitch-switch.o
CCLD freeswitch
/usr/lib64/libnss3.so: undefined reference to `PR_FindSymbol'
/usr/lib64/libnss3.so: undefined reference to `PR_RWLock_Rlock'
/usr/lib64/libssl3.so: undefined reference to `PR_OpenAnonFileMap'
/usr/lib64/libssl3.so: undefined reference to `PR_UnloadLibrary'
/usr/lib64/libnss3.so: undefined reference to `PL_InitArenaPool'
/usr/lib64/libnss3.so: undefined reference to `PR_NewRWLock'
/usr/lib64/libnss3.so: undefined reference to `PR_RWLock_Wlock'
/usr/lib64/libnss3.so: undefined reference to `PR_LoadLibrary'
/lib64/libldap-2.4.so.2: undefined reference to `PR_GetEnv'
/usr/lib64/libssl3.so: undefined reference to `PR_LoadLibraryWithFlags'
/usr/lib64/libnssutil3.so: undefined reference to `PL_ClearArenaPool'
/usr/lib64/libnss3.so: undefined reference to `PR_DestroyRWLock'
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/libcurl.so: undefined reference to `PR_NewTCPSocket'
/lib64/libldap-2.4.so.2: undefined reference to `PR_SetEnv'
/lib64/libldap-2.4.so.2: undefined reference to `PR_GetLibraryName'
/usr/lib64/libssl3.so: undefined reference to `PR_ErrorInstallTable'
/usr/lib64/libssl3.so: undefined reference to `PR_ExportFileMapAsString'
/usr/lib64/libssl3.so: undefined reference to `PR_GetLibraryFilePathname'
/usr/lib64/libssl3.so: undefined reference to `PR_FindFunctionSymbol'
/usr/lib64/libsmime3.so: undefined reference to `PL_NewHashTable'
/lib64/libldap-2.4.so.2: undefined reference to `PR_ErrorToString'
/usr/lib64/libnss3.so: undefined reference to `PR_RWLock_Unlock'
/usr/lib64/libssl3.so: undefined reference to `PR_ImportFileMapFromString'
/lib64/libldap-2.4.so.2: undefined reference to `PR_GetDirectorySeparator'
collect2: ld returned 1 exit status
make[2]: *** [freeswitch] Error 1
make[2]: Leaving directory `/usr/local/src/freeswitch'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/local/src/freeswitch'
make: *** [all] Error 2

To fix this just run:

rm -­rf /usr/local/freeswitch/{lib,mod,bin}/*
git clean -fdx
./bootstrap

GUIs and Utilities

There are a couple user interfaces to Git available with the Git suite. These GUIs require the tcl/tk toolkits installed.

git-gui

Portable graphical interface to Git. See the git-gui(1) man page.

git gui [<command>][arguments] 

gitk

The git repository browser. See the gitk(1) man page.

gitk [<option>...][<revs>][--][<path>...] 

Other Cool Tools

  • tig - Curses-based text GUI for git
  • magit - emacs addon for git. Travis Cross says it is beyond cool!

Git Resources

See Also