Dawnfoster (Talk | contribs) m (typo) |
Heliacorreia (Talk | contribs) (Adding potential useful links.) |
||
| Line 5: | Line 5: | ||
''NOTE'' even though git was developed for the Linux kernel, it is still a source code management system. You can use it for just about everything.... In fact, folks maintain documents, images, and god knows what else with git. Anything that needs version control involving multiple developers across multiple geographies, git is pretty good at it. | ''NOTE'' even though git was developed for the Linux kernel, it is still a source code management system. You can use it for just about everything.... In fact, folks maintain documents, images, and god knows what else with git. Anything that needs version control involving multiple developers across multiple geographies, git is pretty good at it. | ||
| + | |||
= Is there a full form for GIT? = | = Is there a full form for GIT? = | ||
| Line 10: | Line 11: | ||
"I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git." | "I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git." | ||
But then, [http://en.wikipedia.org/wiki/Git_(software)#Name what's in a name huh?] | But then, [http://en.wikipedia.org/wiki/Git_(software)#Name what's in a name huh?] | ||
| + | |||
= Ok great.. I have to learn git, so where do I start? = | = Ok great.. I have to learn git, so where do I start? = | ||
| Line 227: | Line 229: | ||
* git push origin branch - push my local branch to the remote branch | * git push origin branch - push my local branch to the remote branch | ||
* git push origin :branch - delete the remote branch | * git push origin :branch - delete the remote branch | ||
| + | |||
= HANDS ON - Send a kernel patch to a mailing list like MeeGo mailing list!!! YAAAY.. Finally = | = HANDS ON - Send a kernel patch to a mailing list like MeeGo mailing list!!! YAAAY.. Finally = | ||
| Line 517: | Line 520: | ||
So good luck, and let the patches roll :) | So good luck, and let the patches roll :) | ||
| + | |||
| + | |||
| + | = Other links = | ||
| + | You may also want to visit the following wiki pages:<BR> | ||
| + | [http://wiki.meego.com/Gitorious_guidelines Gitorious guidelines]<BR> | ||
| + | [http://wiki.meego.com/Brief_git_guide Brief git guide]<BR> | ||
| + | <BR> | ||
The Tao of Git OR how I stopped getting scared of Git and started using it OR Why the hell aren't you using Git yet ;) ?
Long, long, long time ago, a cool hacker named Linus was faced with a dilemma - the Linux kernel that he and lot of other world wide hackers were using and working on, was hosted on bitkeeper and the owners of bitkeeper were pulling the plug on hosting Linux kernel. Linus knew that without a source code management system which could handle global collaborated code development, the Linux kernel was more or less kaput! Linus rolled up his sleeves and in the ancient respected hacker tradition, wrote a brand new version system - called GIT. more history
NOTE even though git was developed for the Linux kernel, it is still a source code management system. You can use it for just about everything.... In fact, folks maintain documents, images, and god knows what else with git. Anything that needs version control involving multiple developers across multiple geographies, git is pretty good at it.
Linus Torvalds has quipped about the name "git", which is British English slang for a stupid or unpleasant person: "I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git."
But then, what's in a name huh?
It is pretty easy to learn git - there are only 3 fundamental concepts to understand:
A patch is a set of changes (may include multiple files) doing one logical step only.
Lets say Alice has file x:
hello wrold mama mia
Bob gets this file and notices the typo wrold. He has two options:
option 1) Bob walks over to Alice's desk and sees Alice editing file x and tells Alice:
Alice, you have a typo in line 1, change wrold to world.
Option 2) Bob sends Alice a new file x.new with a note that he fixed the typo
hello world mama mia
Well, computers are not too good at English and we have people involved, also, so we need a format which can easily be understood by computer applications, as well as read and shared by humans for humans.
Welcome to Patch. Bob edits file x and fixes the typo and emails the changes to Alice.
diff --git x.old x.new index 835e1c2..f75f149 100644 --- x.old +++ x.new @@ -1,2 +1,2 @@ -hello wrold +hello world mama mia
Explanation:
--- x.old
old file name
+++ x.new
new file name
@@ -1,2 +1,2 @@
this is called a chunk -> each chunk is a change with a bit of code above and bit of code below to give you a context. The -1,2 +1,2 tells you that the changes were made between lines 1 and 2.
-hello wrold
the '-' prefix shows that this line was deleted
+hello world
the '+' prefix shows that this line was added (so in conjunction with the above, shows that no change occurred).
mama mia
the ' ' prefix tells us that no change occured.
Now, Alice can see immediately that there is one file changed, one line changed in that file and the exact change, as well ;).
How did this magic happen? There are two unix utilities from ancient times, diff and patch. They are opposites, diff generates the diff between files and patch applies the diff to the file to be modified.
In our example above, Bob uses the diff program to generate the diff and Alice uses thepatch program to apply the patch.
Good things:
Bad things:
Now back to git - git works with patches:
A git commit is a single patch, here is the git patch if Bob was working on git. Yeah, we will discuss how to generate and work on patches in later sections, but hold on to your horses for a minute here.
From dd392da509bec9f7cd3a8b282c0386f8fcbc35d8 Mon Sep 17 00:00:00 2001 From: Bob <bob@somwhere.com> Date: Fri, 7 May 2010 13:34:20 -0500 Subject: [PATCH] fix typo of world world has the wrong spelling --- x | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/x b/x index 835e1c2..f75f149 100644 --- a/x +++ b/x @@ -1,2 +1,2 @@ -hello wrold +hello world mama mia -- 1.6.3.3
Aah, more information than an ordinary git file. Git patches are designed to be:
Lets do a line by line explanation here.
From dd392da509bec9f7cd3a8b282c0386f8fcbc35d8 Mon Sep 17 00:00:00 2001
This gives an commit ID for this patch.
From: Bob <bob@somwhere.com>
Who is this patch from? the format is Name <email id>
Date: Fri, 7 May 2010 13:34:20 -0500
Date when the patch was generated
Subject: [PATCH] fix typo of world
The subject [PATCH] says the type of email. Presto, you've got a patch, and fix typo of world tells Alice what this patch is about.
world has the wrong spelling
This is the detailed message or the body of the patch - explanations of what we do are good idea to have here. (we learn more of this later on - we use the term commit message in git context)
---
patch uses the -- as a sectional thing. the first --- till diff is considered the diffstat section - things added below this line till the first diff are not committed into the git repository when merged
diffstat is diff statistics -> essentially the statistics information of files changed, lines deleted and added, etc.
x | 2 +-
file name | file change statistics histogram - shows total lines changed (deleted and inserted) and a +- based ascii graph.. usually with large number of files changed, this is a handy thing to see which file was largely impacted.
1 files changed, 1 insertions(+), 1 deletions(-)
Ok this is too obvious right?
diff --git a/x b/x index 835e1c2..f75f149 100644 --- a/x +++ b/x @@ -1,2 +1,2 @@ -hello wrold +hello world mama mia
we already dealt with this previously.
-- 1.6.3.3
Another git ignored section information ;). This just gives you an idea which version of git was used to generate the patch.
Voila! And that is all that a patch is, diff information organized in a certain way.
A branch is a simple concept. It is a version of the original s/w, on which a specific feature/operation is being done.
There is one exception though, the master branch -> This is the branch which has everything integrated. You can have multiple branches inside a single repository, each branch can have multiple patches independent of the other branch. Typically, a git repository looks like the following
master |-- for-next-opp |-- sdp-fix | `-- gpmc-test `-- wip-smartreflex
OR represented as a directory form it'd look like:
origin/master origin/master/for-next-opp origin/master/wip-smartreflex origin/master/sdp-fix origin/master/sdp-fix/gpmc-test
But you get the picture. Each branch does something, you spawn off to do something else, like me working on 4 different things at the same time on the same tree, so i can switch whichever git branch that I fancy to work on and commit my changes there, then switch somewhere else and do something else altogether, etc.
origin -> the branch from where everything came from. We could even have the same repository contain multiple trees. Ok, that is a bit too much for the moment. Let's keep it simple and understand the naming conventions. There are a few generic ones in kernel community:
TIP We all work on multiple things at the same time and interruptions to work on something else is normal (even though not desirable).. ALWAYS use git branches to organize your work, it is meant to make your life easier. ;)
Do this:
mkdir test_dir cd test_dir git init
Voila! You now have your own git repository, a.k.a tree. Tom, Dick, Harry, Alice, and Bob can have their own tree. They can clone (or copy) from each other's tree. Each repository(tree) will have multiple patches as commits on it and contributions can take place towards every other tree.
In general, in a community working on a common software, there is usually a primary tree (repository) or a final tree. In the example of Linux kernel, it is linus' tree. All code has to get there eventually. How is this decided? Essentially, it is a community consensus to have one person maintain the final code, or the final integrated code. Obviously, there is no point in Tom, Dick, Harry, Alice, and Bob all having their own changes without integrating in a central point.
There are lots of kernel trees, but main trees are usually hosted here. To take TI OMAP kernel trees as an example, it tends to be a little complex, as follows:
OMAP Specific code: Tony -> Linus
OR
ARM Code: Russell -> Linus
OR
Power management core: Rafael -> Linus
etc. Tony, as a platform maintainer, maintains his own tree, so do Russell and Rafael.... You can also maintain your own tree here if you like. ;) But the point to note: there are community accepted maintainers, just another smart engineer who usually takes the pain to align a bunch of similar folks chattering around with code ;)
git can understand git(yeah git) protocol, http/https protocols, ssh, ftp, and bunch of other protocols and can even make a copy from one local directory to another local directory. the git tree is visible using normal commands such as ls, or you can view your tree with a tool like qgit, gitk, etc., or even over the web, like gitweb. For command line fans, you can use tig, which lets you study a git tree in a GUI-like environment using just the console.
Someone sends you a link like http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=summary and tells you platform X code is out there, clone and build it. Open the link and you will see:
URL git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
To clone (or download/copy) the tree, just do a git clone link. voila! You now have a copy!
Important thing to remember with git -> every repository is a complete repository - You don't need a network (unlike clearcase dynamic views, if you've used it) or anything other than your own machine. Any patch from Alice to Bob should be shared by either exposing the git repository over one of the protocols (like setting up your own apache webserver and exposing your git repo there) or generating and sending out your patches from your repo to other users by email. If you cloned the tree, you have your own tree now. But try not to keep your changes in your tree forever. The rule in opensource is "release often, release to upstream" (ok that was a plagarized version of this ;) ).
Alright, time to stop the blah blah and do some coding. So, let's actually go hands on from cloning a tree, modifying it, generating a patch, getting it ready, and posting it upstream.
Remember the MeeGo rule: If a patch is for a project that has an upstream version, post it there first!
Let's try and do something tricky -> We are going to enable missing ethernet GPIO mux for SDP3630 and send the patch to the MeeGo Mailing list.
on Ubunto 9.10:
sudo apt-get install git-core git-email qgit
To set up the environment so that you can clone a git tree inside your organization
That is rather simple: just do
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
once this is done,
cd linux-2.6
You will be in the repository.
$ git branch -va * master 5fe8321 Merge branch 'x86-x2apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip remotes/origin/HEAD -> origin/master remotes/origin/master 5fe8321 Merge branch 'x86-x2apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
We did a git branch -va here. The -v shows a verbose description of where the branches are (commit ID of the HEAD, or topmost commit in a branch), and the commit message. The -a shows all hidden branches, by default the remote branches are usually hidden, so you need a -a to show them.
Notice how the * points to master -> the * points to the branch you are currently on.
In other trees maintained by maintainers, you'd see additional branches in remote, as well. To pull a similar branch gpio_development that a maintainer has, do the following:
git checkout -b gpio_development --track origin/gpio_development
This means the following:
-b (create a local branch) --track -> keep track of remote branches, so that next time you do a pull, the local branch will reflect all changes in remote branch. :)
So now, I have a local branch for gpio_development, which is in sync with remote gpio_development branch in maintainer x's tree ;). It is no longer required to use --track in recent version of git, since it is now the default behavior, when doing a checkout of a remote branch.
Exercise:
git branch -v git branch git checkout master git branch -v git checkout gpio_development git branch -v
See how these commands differ and the resulting behavior, use the man pages to better understand how these commands work. (such as, man git-branch or man git-checkout)
Next, I create a sub-branch to work in. This is where I will make my changes.
git checkout -b ether-mux
ether-mux does not exit in my tree, so -b will create a branch called ether-mux and git checkout will ensure that I am on that branch. I can alternatively do the following:
git branch ether-mux git checkout ether-mux
Essentially, both do the same thing, but the -b is a wee bit faster since you don't need to type too many commands. :)
Before we write code, let's read a bit on what the ancient masters tell us from their collective wisdom.
Disclaimer: I have borrowed this from here
The following Linux documentation must be read before anything:
scripts/checkpatch.pl is a script that facilitates better kernel code, and can be used to check many coding style rules.
This script applies on patch files by default, but can also process complete source files using the -f option. To get a list of options, run:
checkpatch.pl -h
This (script is an example used to easily call the checkpatch.pl script on a series of files (to run periodically during your development, for example).
You can also set up GIT to run checkpatch automatically before each commit (and reject it on failure). You need to copy the attached script into your GIT repository under $GIT_DIR/hooks directory (normally as .git/hooks/pre-commit). This script also runs git diff --check, plus as an added benefit, it sets file permissions for common files (c, h, makefile, README) to 0644, and executables (directories, shell scripts) to 0755. This is a common issue when editing files in Windows.
If you want to bypass the check (for example, if the failure is intended), use the -n flag for commit to ignore the checks. Just be sure that you still resolve any failures that were correct, and there really wasn’t a better, proper way to write your code without checkpatch errors. Now there is a whole set of discussion about the 80 character limit that sometime forces less understandable code (you can read about the pros/cons [1] and find a patch [2] to checkpatch to make this optional) BTW, Linus prefers [3] in many cases, to ignore the 80-char-limit warnings.
But wait! You can do even more. Since you are already modifying files, why not run checkpatch on the whole file (and not just on the lines you are changing)? To see if there are any already existing checkpatch errors in the files that you modified, set up these two bash aliases that will run checkpatch on the whole files that are about to be committed (just run ‘chkp’):
alias gitd='git rev-parse --show-cdup'
alias chkp='`gitd`scripts/checkpatch.pl -f `git diff --name-only HEAD | awk -v i=$(gitd) "{print i\\$0}"`'
Note: It is always recommended to run checkpatch.pl with --strict to get better warnings.
sparse is a static code analysis tool that shall be run on all source files heading a kernel release.
Luckily, sparse is integrated into the kernel build-system and can be easily invoked.
Example for a single file:
make C=2 drivers/hsi/hsi.o
Example for a complete folder with some filtering on some error messages:
make C=2 drivers/hsi/ 2>&1 | grep -v __cold__
Now that we know some of the terms, let's write some code. In my case, I am editing the file arch/arm/mach-omap2/gpmc-smc91x.c I added mux.h inclusion and add the following logic:
if (omap_mux_init_gpio(gpmc_cfg->gpio_irq, OMAP_PIN_INPUT)) {
pr_err("%s: Unable to init mux for smc gpio\n", __func__);
gpio_free(gpmc_cfg->gpio_reset);
goto free3;
}
Since I wanted the mux to be done for the provided gpio number.
Remember the golden rules:
rm arch/arm/mach-omap2/gpmc-smc91x.o; mymake C=1 arch/arm/mach-omap2/gpmc-smc91x.o
$ git branch -v * ether-mux e1fc6fa Linux-omap rebuilt: Updated to -rc6, merged updated for-next master e1fc6fa Linux-omap rebuilt: Updated to -rc6, merged updated for-next $ git status # On branch ether-mux # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: arch/arm/mach-omap2/gpmc-smc91x.c # # Untracked files: # (use "git add <file>..." to include in what will be committed) # [...] no changes added to commit (use "git add" and/or "git commit -a")
Ok, so I am ready for the next step.
If you are modifying multiple files, you have various options, but mainly organize the changes in logical order per commit. Remember each commit is a separate patch, each patch can modify more than 1 file, but should be a single logical change. Here you have two options:
git commit -a -s
commit all changes that you did in the code in a single shot. OR
git add file1 file2... git commit -s
This will commit only the files which you add with git add. Note: The -s will add a signed-off-by with your details automatically.
You must have seen that the git comments are used to populate the patch file header in the format-patch phase:
But pay attention that the comment will be integrated to the email sent by git-send-email, only if there is a blank (empty) line between the 1st line comment (used as subject) and the rest of the comment lines.
Example of a commit comment:
This is the 1st line, that will be used as patch subject This is the 3rd line of comment (intentionally left 2nd line empty so that this part of comments are integrated into the emails).
Suggestions for Commit messages: Commit messages are informative for reviewers and maintainers. Remember, once the patch is submitted, it has a long way to go through various maintainers and mailing list members before reaching kernel.org. You need to put yourself in the shoes of maintainers and reviewers who may or may not be familiar with all the internal details after a few months of time, but still need to understand the motivation for a change.
A commit message is structured:
Some of the above points might be self evident and could be skipped, but it is usually a good idea to be descriptive enough. Again, it is a fine balance between being informative and going overboard. Community members and maintainers are usually kind enough to help guide a patch in.
Read this and this for more detailed rationale.
Note: in the case of MeeGo, DO add:
kernel.org status: upstream | commit ID: eda345
kernel.org status: accepted | link: link to patch
kernel.org status: under discussion | link: link to the public discussion
kernel.org status: wont be published | reason: state reason here (such as, temporary hack)
In my case:
omap3: smc: enable mux for ethernet Enable mux mode for GPIO pin for the interrupts to come in. This is specifically useful for bootloader-less kernel booting using configuration header as the u-boot does not exist for configuring mux values before hand for the system.
kernel.org status: wont be published | reason: demo only
Signed-off-by: Bob someone <bob@somewhere.com>
# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch ether-mux
Note: If you committed anything and forgot to update/need to change the previous, don't panic. :)
git add new_changed_file git commit --amend
This will re-commit the last committed patch with the changes you just did, that is, it replaces the previous one.
Now that we have committed our changes, time for us to send this patch out!
Subject: [PATCH $version $n/$total] $subsystem: one-line summary
(keep the one-line summary < 50 chars)
first create a temporary directory where you want the patches to reside:
mkdir ../smc-patches
The easy part -> here, based on the number of commits, you have multiple options: If there is a single commit:
git format-patch -s -M -o ../smc-patches master..
this generates the patches, where
If there are multiple commits:
Example:
git format-patch --cover-letter -n -s -M -o ../smc-patches
you will find a patch 0000-cover-letter.patch -> this has to be manually edited. example:
From e5d1394f93b2f972a516daaf55967871b4bf8c0e Mon Sep 17 00:00:00 2001 From: Bob someone <bob@somewhere.com> Date: Fri, 7 May 2010 20:23:46 -0500 Subject: [PATCH 0/2] *** SUBJECT HERE *** *** BLURB HERE ***
Replace the subject and BLURB with enough detail, and leave the rest of the file mostly intact, unless you'd like to edit information there.
As we discussed earlier, Linux kernel includes a script called scripts/checkpatch.pl - use it to ensure your patch has no problems
$ scripts/checkpatch.pl --strict ../smc-patch/0001-omap3-smc-enable-mux-for-ethernet.patch total: 0 errors, 0 warnings, 0 checks, 19 lines checked
../smc-patch/0001-omap3-smc-enable-mux-for-ethernet.patch has no obvious style problems and is ready for submission.
This is what you want to see: 0 error, 0 warning. :) If all is good, you are ready to send the patches out.
First set up your Linux PC to send the patch. For example, in your organization, you may want to follow [| this]
alias gsend='git send-email --smtp-server /usr/bin/msmtp --from "My Name <someone@somewhere.com>" --envelope-sender="My Name <someone@somewhere.com>"'
WARNING of course, you need to change the My Name and someone@somewhere.com to something that represents you :) Here:
Remember by default, git send-email will add all folks who are in From:, Cc: Signed-off-by: tags to the email Cc:
Tip: It would be wise to modify the gsend alias in your ~/.bashrc or ~/.bash_aliases file as needed to automatically add it on login.
Tip: Send this patch to yourself first with --suppress-cc=all. Review it as if a third party, who has no clue what you did, is reading your patch. Remember, when you send a patch to a list, you are asking folks to read and agree to your changes. Linux is a community thing. We all own responsibility for the resulting code :).
When you are posting upstream for the Linux kernel, you have a script called scripts/get_maintainer.pl, use it scripts/get_maintainer.pl 0001-my-patch.patch (just like you'd use it with checkpatch.pl). It spits out a list of email IDs. It is usually a good idea to add most folks and selectively include the mailing lists, based on what audience you seek. Recently however, the suggestion has been to use get_maintainer.pl --no-git to reduce the spam in public mailing list. This option will choose from just the MAINTAINER file the email IDs to post to.
So good luck, and let the patches roll :)
You may also want to visit the following wiki pages:
Gitorious guidelines
Brief git guide