Open menu with table of contents Git Introduction
Logo of Stuttgart Media University for light theme Logo of Stuttgart Media University for dark theme
Android Development

Git Introduction

Stuttgart Media University

1 Agenda

  • Basics about Git
  • SSH key for the HdM GitLab
  • Clone your repository
  • Working locally: status, add, commit, log, diff
  • .gitignore for Android projects
  • Remote repositories: push, fetch, pull
  • Branching, merging and resolving conflicts
  • Team workflow with Merge Requests
  • Git clients

2 Basic About Git

  • Git was initially created during the development of the Linux kernel by Linus Torvalds and others in April 2005.
  • It's a free and open source distributed version control system. That's the official website.
  • A version control system allows keeping historical versions tracked and improves the collaboration in the team. It can be used as single source of truth when it comes to code which also allows to automate building applications with e.g. continuous integration (CI). The place where it's stored is called a repository.
  • The concept is working locally on a separate branch and then push it to make it public to the team. If it's tested and working, your changes can be merged to the main or master branch. The main branch should always work!
  • Please check this Git cheat sheet for a quick overview.

3 SSH Key for the HdM GitLab

GitLab authenticates git clone/git push over SSH with a key pair. You do this once per computer.

# 1. create a key pair (accept the default file name, a passphrase is optional)
ssh-keygen -t ed25519 -C "your-hdm-account@hdm-stuttgart.de"

# 2. print the public key and copy the whole line
cat ~/.ssh/id_ed25519.pub

# 3. GitLab > avatar (top right) > Preferences > SSH Keys > Add new key: paste it

# 4. test the connection, GitLab answers with "Welcome to GitLab, @<account>!"
ssh -T git@gitlab.mi.hdm-stuttgart.de
  • Never share the private key (id_ed25519 without .pub), only the public key goes to GitLab
  • Alternative: clone with HTTPS and log in with your HdM account, then Git asks for the password on every push
  • Details: GitLab docs: Use SSH keys

4 Clone Your Repository

To initialize a new project you would call git init. This is not needed in our case: every participant gets a repository with the folder structure for the assignments, and every team gets a project repository. So please do:

git clone git@gitlab.mi.hdm-stuttgart.de:mad-android/<semester>/<hdm-account>.git
cd <hdm-account>
  • Copy the real URL from your project in GitLab (blue Code button, "Clone with SSH"). <semester> is e.g. ss26, <hdm-account> is your HdM login
  • The project repository of your team has its own URL in the same namespace
  • After cloning you are on the main/master branch and origin points to the GitLab repository

5 Working Locally

Create a new file in the repository, e.g. assignment1/readme.md, then:

git status                       # which files are untracked or modified?
git add assignment1/readme.md    # stage the file (git add . stages everything)
git commit -m "Add readme for assignment 1"
git log --oneline                # history, one line per commit

Before committing, check what you have actually changed:

git diff                         # unstaged changes compared to the last commit
git diff --staged                # staged changes that will go into the next commit
  • Commit small, logical steps with a message that says why, not only what
  • A commit is local until you push it

6 .gitignore for Android Projects

A .gitignore file lists what Git must never track. For an Android Studio project these must stay out of the repository:

# generated build outputs, re-created by Gradle on every build
build/
.gradle/
.kotlin/
*.apk
*.aab
# IDE settings of your machine
.idea/
*.iml
# machine specific paths and secrets (SDK location, OMDB_API_KEY)
local.properties
  • Android Studio generates a .gitignore in the project root and in app/ for every new project, the starter projects of the assignments already contain it
  • If something is already tracked, .gitignore does not help: git rm -r --cached build/ removes it from the index
  • Reference: Android.gitignore

7 Working with a Remote Repository

While working in a team we have a remote repository, in our case hosted on the HdM GitLab. Push your local commits:

git push origin master           # or main, depending on your repository

Team members made changes and you want to get them:

git fetch origin                 # downloads the new commits, changes nothing in your working copy
git pull                         # = git fetch + git merge origin/<current branch>
  • git fetch lets you look first (git log --oneline master..origin/master), git pull integrates right away
  • If the push is rejected ("fetch first"), somebody pushed before you: git pull, resolve conflicts if any, push again
  • For the assignments only the main/master branch is graded, make sure your final state is pushed there

8 Branching

In a team, each member works on a different feature in an own branch with main/master as the base:

git switch -c feature1           # create the branch and switch to it
git branch                       # list branches, * marks the current one
git switch master                # switch back
git switch feature1

git switch exists since Git 2.23 and only switches branches. The older git checkout does the same but also restores files, you will still see it in many tutorials:

git checkout -b feature1         # same as git switch -c feature1
git checkout master              # same as git switch master

9 Merging

You did your work on feature1, added files and committed them. Now the feature should go into main/master:

git switch master
git pull                         # get the latest master first
git merge feature1               # merge the branch into master
git push origin master           # the merge is local until you push
git branch -d feature1           # delete the branch when it is no longer needed
  • Git merges automatically when both branches changed different lines
  • If the same lines were changed on both sides, Git stops with a conflict and asks you to decide

10 Resolving a Conflict

$ git merge feature1
CONFLICT (content): Merge conflict in app/src/main/java/.../MainActivity.kt
Automatic merge failed; fix conflicts and then commit the result.
<<<<<<< HEAD
    Text(text = "Clicked $counter times")
=======
    Text(text = "You clicked $counter times")
>>>>>>> feature1
  • Open each conflicted file (git status lists them), keep the version you want or combine both, delete the <<<<<<<, =======, >>>>>>> markers. Android Studio shows this as a three-way diff (Git > Resolve Conflicts)
  • Mark the file as resolved with git add <file>, then finish with git commit (the merge message is pre-filled)
  • git merge --abort throws the merge away and brings you back to the state before the merge

11 Team Workflow with Merge Requests

The project is done in teams of 2-4. Nobody pushes directly to main/master, changes go through a Merge Request (MR):

  1. git switch -c feature/search-screen and commit your work on this branch
  2. git push -u origin feature/search-screen, GitLab prints a link to create the Merge Request
  3. Open the MR in GitLab: describe the change, assign a team member as reviewer
  4. The reviewer reads the diff, comments in GitLab, you push fixes to the same branch (the MR updates itself)
  5. Approve and Merge, let GitLab delete the source branch. Everybody runs git pull on main/master
  • Small MRs are reviewed faster and conflict less
  • Pull main/master into your branch regularly (git merge master on the feature branch) to keep conflicts small
  • A merge request pipeline (GitLab CI) can run ./gradlew test before anyone reviews
  • Docs: GitLab Merge Requests

12 Git Clients

If you have issues using Git in the command line you can of course use a Git client. Popular ones:

13 Summary

  • Set up an SSH key once, then clone your assignment repository from the HdM GitLab
  • status, add, commit, log --oneline, diff are the daily local commands
  • .gitignore keeps build/, .gradle/, .idea/, local.properties and APKs out of the repository
  • push publishes commits, fetch downloads, pull = fetch + merge
  • Work on branches (git switch -c), merge into main/master, resolve conflicts by editing the markers, add, commit
  • In the team: feature branch, push, Merge Request, review, merge

14 Recap Questions

  • What is the difference between git fetch and git pull?
  • Why must local.properties never be committed? What else belongs into .gitignore of an Android project?
  • What does git switch -c feature1 do, and which older command does the same?
  • Git reports a merge conflict. Which three steps resolve it?
  • Why does a team work with Merge Requests instead of pushing to main/master directly?

Questions?