[Nexus 6P Android Development] nathanchance:
How to do your own modifications to the kernel

Introduction

When I was getting started with compiling kernels, I relied a lot on Google and git documentation (this website is the best) to get what I wanted to accomplished. As a lot of that reading can be kind of dense. I decided to boil it down to the few commands and procedures you will need to modify this kernel (or any git repo).

LEARN GIT FROM THE COMMAND LINE. Seriously, do not use a program like SmartGit, it will cripple you and your workflow and potentially screw up authorship. Do it the right way using this guide.

Note:

This is NOT supposed to be a super technical guide/how-to on Git. If there is something that is glaringly inaccurate, I will fix it but I am not going to add a ton of extra text here as there are plenty of Git tutorials you can easily find with Google. This is a crash course.

Git Introduction

What's a git?

Git is a version control system that allows developers to keep track of their changes to code. This is extremely helpful when working with large amount of code and changes across a large range of files (such as a kernel or ROM) as it allows you to easily revert or add changes as you see fit.

Terminology

These are not super precise definitions (you can find technical ones by Googling "what is a <word> git"):

Repository: the location that holds all of your code changes and files (this can be local or remote).

Commit: a change to your code

Branch: different snapshots of your code

Cloning: copying a remote repo to a local one

Forking: copying a repo (either remote or local) and making changes to it without affecting the other

Reading Github

Github is the most popular site for hosting git repositories. This is what my repo is hosted, which I will be using for my example. If you go to https://github.com/nathanchance/Ninja-Kernel, you will be greeted with this screen:

Here we will unpack those terms above. The repository (that view) contains files. At the top, you will see a tab called Commits. Clicking on this will bring you to a view similar to this:

This is a full list of the changes to the repository. The name of the commit message generally describes what it does and clicking on the title of the commit will bring you into the detailed view:

In this commit, I have renamed the version from 1.1.1 to 1.2. Some commits will be very small like this, others won't be. Additionally, in the righthand corner of the commit message, you'll see a commit hash (bunch of numbers and letters). That will come in handy later.

Back on the home page of the repo, if you click on the branch dropdown, you will see the various different branches of the repo:

If you click on a branch (let's do n in this case), you'll be brought to a page similar to the home page but there may be different commits in the commits tab. In this case, I have committed version 2.1 instead of 1.1:

This should help you navigate around Github and find commits you may want to merge.

Git Documentation

Throughout the next sections, I will be using commands to show you how to modify the source. This section goes over the command format, what it does, and an example.

git clone

Format:

# Clone a repo into a directory the same as its remote name
git clone <url>

# Clone a repo into a directory with a specified name
git clone <url> <name_of_folder>

What it does:

- Copies a remote repo into a folder on your computer

Example:

git clone https://github.com/nathanchance/Ninja-Kernel.git
git clone https://github.com/nathanchance/Ninja-Kernel.git Ninja

Screenshot:

git checkout

Format:

# Changes to the specified branch (if it does not exist, it creates one)
git checkout <branch>
# Creates a new branch based off the specified one
git checkout -b <branch> <branch_to_be_based_on>

What it does:

- Whenever you want to make changes to files, you need to make sure you are on the right branch. You can see what branch you are currently on by running git branch; if you are on a different one, switch to the right one using the above commands

- If you want to create a new branch, use the second command.

Example:

# Switches to the m branch
git checkout m
# Creates a new branch "new-branch" based on old-branch
git checkout -b new-branch old-branch

Screenshot:

git add

Format:

# Adds a file to the staging index
git add <file>

# Adds all of the changed files to the staging index
git add -a

What it does:

- This adds a file to the list of changes to commit (staging). So let's say you modify the README of your repo, deleting a line, and adding one. In order to register that change, you need to add the file to your staging index.

Example:

# Adds the file README to the index
git add README

Screenshot:

git status

Format:

# Tells you what the status is of your repo
git status

What it does:

- Allows you to see what files you have staged for commit, where you are relative to where you are with your remote

Example:

Screenshot:

git commit

Format:

# Commit your changes and bring up a nano window to write your message
git commit

# Commit your changes and create the message as a parameter
git commit -m "Commit message here"

What it does:

- Saves all of your staged changes in a commit

Example:

git commit -m "This is a test commit message"

Screenshot:

git revert

Format:

# Undoes the changes by a certain commit
git revert <hash>

What it does:

- Undoes the commit you have chosen.

- NOTE: It is a good idea to add to the commit message why you are reverting a commit so people don't have to guess (did you not like it or did it break something?)

Example:

git revert 18d72d42648de9fde9bedcc810a936e0d253af9c

Screenshot:

git pull

Format:

git pull

What it does:

- Retrieves the latest changes from your remote repository (like Github)

Screenshot:

git push

Format:

git push

What it does:

- Opposite of git pull, it sends your latest changes from your local repository to the remote

Screenshot:

git fetch

Format:

# Fetches the commits from the main branch of a remote repository
git fetch <url>

# Fetches the commits from the specified branch of a remote repository
git fetch <url> <branch>

What it does:

- Whenever you want to merge or cherry pick something from a repository other than your own, you need to fetch it so git knows where to pull commits from.

Example:

# Fetches the commits from the n branch of my repo
git fetch https://github.com/nathanchance/Ninja-Kernel.git n

Screenshot:

git merge

Format:

# Merge one branch of your repo with the current one
git merge <branch_to_merge>

# Merge a remote branch into the current one
git merge <remote>/<branch_to_merge>

What it does:

- Takes the commits in the specified branch and merges the ones that are not present in the current branch.

Example:

git merge n

git cherry-pick

Format:

# Takes a commit either from another branch or the list you fetched and merges it into your current branch
git cherry-pick <hash>
# Pick a range of commits
git cherry-pick <hash_1>^..<hash_2>

What it does:

- If you have a commit in another branch and want to merge it into your current branch, get the hash either from Github if pushed or git log (below) and run git cherry-pick

- If you have a commit in a remote repo you want to merge into your current branch, fetch the remote repo and run git cherry-pick with its hash (found on the remote repo's website)

Example:

git cherry-pick 68a8ff686ccb2ff01cbaa7b2704c4da6c066ecc8
gcp 7204eedd1076bd87c624aab4fb9c0cc6ac50933b^..102a72b895afb063240fb09292c17e11155e8dd9

Screenshot:

git log

Format:

# Brings up a list of commits with their full messages and hashes
git log
# Brings up a list of commits with the title of their message and full hashes
git lot --format="short"
# Brings up a list of commits with short hashes and messages
git log --oneline

What it does:

- This command allows you to see the revision history of your local repo

Screenshots: (git log, git log --format=short, then git log --oneline

How To's

Merge Android security updates

There are two ways to do this (I personally recommend cherry-picking)

1. Cherry pick the individual commits

1. Fetch Google's repo

Google's kernel repository is located here: https://android.googlesource.com/kernel/msm/

Currently, Angler is on the branch android-msm-angler-3.10-marshmallow-dr1.6-1

Thus, the command looks like this:

git fetch https://android.googlesource.com/kernel/msm/ android-msm-angler-3.10-marshmallow-dr1.6-1

2. Figure out which commits you need to pick

Click on the branch you want to merge commits from in Google's list

Click on the "log" link next to the commit hash

In that list, find the first commit at the top of the list and open it in a new tab (now referred to as the last commit)

Start skimming the list, looking for the next commit that has a green android-6.0.1_r# next to it

Open the commit right above that commit (now referred to as the first commit)

Copy the individual hashes of the first and last commit (make sure to know which is which!)

3. Pick the commits!

git cherry-pick <hash_of_first_commit>^..<hash_of_second_commit>

Example

Commit log located here: https://android.googlesource.com/kernel/msm/+log/android-msm-angler-3.10-marshmallow-dr1.6-1

First commit: https://android.googlesource.com/kernel/msm/+/46b9920417db45ee0a93f16a07e80666219446d3

Last commit: https://android.googlesource.com/kernel/msm/+/909746bb5e4be07344b4fe4ce95c57fbfc8d9595

git fetch https://android.googlesource.com/kernel/msm/ android-msm-angler-3.10-marshmallow-dr1.6-1
git cherry-pick 46b9920417db45ee0a93f16a07e80666219446d3^..909746bb5e4be07344b4fe4ce95c57fbfc8d9595

2. Merge the whole branch

1. Add a remote

Google's kernel repository is located here: https://android.googlesource.com/kernel/msm/. A remote allows us to easily fetch a repo we use often. To add a remote, follow the below format:

git remote add <name> <url>

In this case:

git remote add aosp https://android.googlesource.com/kernel/msm/

Example:

2. Fetch the repo

Format:

git fetch <name_of_remote_above>

Example:

git fetch aosp

3. Merge the branch

On the left of Google's website, you will notice there are some branches. Currently, Angler is on android-msm-angler-3.10-marshmallow-dr1.6-1 (you can tell by the commit date of the first commit)

The format looks like this:

git merge <name_of_remote>/<branch_to_merge>

Example:

git merge aosp/android-msm-angler-3.10-marshmallow-dr1.6-1

Merge new Linux kernel updates

1. Fetch the kernel.org repo

We are on the 3.10 branch of the stable repo: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git

git fetch git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.10.y

2. Figure out which commits you need

Go to the kernel.org website

In the 3.10 line, click browse

You will be presented with a full list of commits

Open the first one in a new tab (which should be something in the form of "Linux 3.10.y" (now known as last commit)

Use the next link at the bottom of the list and skim through the list of commits until you see the next commit in the form of "Linux 3.10.y"

Open the commit directly above the previous commit (now known as the first commit)

Copy the hash of the first and last commits (making sure you know the difference!)

3. Pick the commits

git cherry-pick <hash_of_first_commit>^..<hash_of_last_commit>

Example

First commit of 3.10.102: https://git.kernel.org/cgit/linux/k.../?id=ce9588a047eae53baf1607a408a8d1d5363f5fde (found on this page)

Last commit of 3.10.102: https://git.kernel.org/cgit/linux/k.../?id=ca1199fccf14540e86f6da955333e31d6fec5f3e (found on this page)

git fetch git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.10.y
git cherry-pick ce9588a047eae53baf1607a408a8d1d5363f5fde^..ca1199fccf14540e86f6da955333e31d6fec5f3e

If you get any conflicts. resolve them using the fix merge conflicts section below.

Add a feature from another kernel

I will be using [MENTION=4684315]flar2[/MENTION]'s wake gestures as an example but this process will work for any set of commits. I have provided a Git example repo here. On the aosp-latest branch will be the latest kernel source from AOSP. If you want to follow along in this tutorial, clone that repo and checkout the branch like so:

git clone https://github.com/nathanchance/Git-Example.git && cd Git-Example && git checkout aosp-latest

1. Figure out which commits you need

This can be a little bit tricky. When adding a feature, there may be more than one commit you need to grab. The trick I use for figuring out if this is the case is going into the detailed commit view (take this commit for example), copying the location of one of the files changed, going back to the head of the repo (in this case, here), navigating to that file, and clicking the history button in the right hand corner. This should give you something like this:

Now copy all of the commit hashes (you can click the little arrow clipboard icon next to the commit message to do this automatically. That gives us this list for wake gestures:

12cea9ee691f9794d3b0a76c6b381b4bde670bda

f4286dee51fde5c1082732381c9474c8381b8fb6

4c9e7f3f63eaf7514154633d320a6d4dd4f94831

5d10751af74617c23dfaf93bdf8149e39ce6da41

79d2aae008e51ed32d64e8a4a1dcf03231a22439

6495a2b15e501ce81bb58d39edd5923d52c2e45f

37daa721971b17a01d503c6dfa66c7c93b7cde2d

2. Fetch the repo

Now we need to fetch the repo that has the commits we need (in this case, the ElementalX repo).

git fetch https://github.com/flar2/angler.git ElementalX-1.00

Example:

3. Pick the commits

After fetching the repos, make sure you are on the proper branch using git checkout and git branch. Once this looks good, run git cherry-pick with the hashes:

git cherry-pick 12cea9ee691f9794d3b0a76c6b381b4bde670bda
git cherry-pick f4286dee51fde5c1082732381c9474c8381b8fb6
git cherry-pick 4c9e7f3f63eaf7514154633d320a6d4dd4f94831
git cherry-pick 5d10751af74617c23dfaf93bdf8149e39ce6da41
git cherry-pick 79d2aae008e51ed32d64e8a4a1dcf03231a22439
git cherry-pick 6495a2b15e501ce81bb58d39edd5923d52c2e45f
git cherry-pick 37daa721971b17a01d503c6dfa66c7c93b7cde2d

Screenshot:

In this case, I was lucky not to have any conflicts. If you try to pick something and there are differences between the code that conflict, you'll get a merge conflict which you will need to fix before committing the cherry pick.

4. Check for any conflicts

Now when you merge a feature, you may need to enable in your defconfig. In this case, we need to add the line CONFIG_WAKE_GESTURES=y (tells the compiler to build the wake gestures module and add it). You can see an example of this here and here.

Fix merge conflicts

I'm not going to explain it any better than these guides :p

https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line/

https://githowto.com/resolving_conflicts

http://stackoverflow.com/questions/161813/how-to-resolve-merge-conflicts-in-git

Special note: Authorship

Authorship is very important in the open source world, as it is what allows people to determine who is responsible for the commit and receive the proper credit. The general rule of thumb is if you didn't think of the idea and write the code, you are not the author. If you are cherry-picking properly, authorship should be automatically maintained; however, if you have to commit something that isn't yours or do some other wonky stuff, you may become the author. No worries though, it is very easy to fix it!

Apply authorship during commit:

Format:

git commit --author="Full Name <email@email.com>"

Example:

git commit --author="Nathan Chancellor <natechancellor@gmail.com>"

Screenshots:

Apply authorship after commit

Format:

git commit --amend --author="Full Name <email@email.com>"

Example:

git commit --amend --author="Nathan Chancellor <natechancellor@gmail.com>"

Screenshots:

Note: if you have already pushed your commit, you will need to amend the commit and force push it to change it:

git push origin --force