In this guide, we will cover the basics of Git, useful features on GitHub, and some advice for using these two tools as a team.
- Git & GitHub
Git is a popular what is version control system, which tracks and manages changes to files (like source code) over time, creating a complete history, enabling collaboration, and allowing developers to revert to previous versions if errors occur.
Git is often used to work on code with others. It also allows you to save the entire history of your codebase, go back to points in history, selectively undo changes and more. Git stores this information in the .git folder of a repository.
There are other version control systems such as SVN and Mercurial. However, since Git is decentralized, more flexible than these systems, and widely used in the industry, we will focus only on Git here.
- Repository: A folder where Git tracks your project and its history.
- Clone: Make a copy of a remote repository on your computer.
- Stage: Tell Git which changes you want to save next.
- Commit: Save a snapshot of your staged changes.
- Branch: Mechanism which allows you to work on different versions or features at the same time.
- Merge: Combine changes from different branches.
- Pull: Get the latest changes from a remote repository.
- Push: Send your changes to a remote repository.
You can download Git for free from git-scm.com. You will need to enter your email after installation.
Afterwards, you will be able to use Git from your terminal or command prompt.
You will likely be prompted to setup your account before you do anything with Git. Simply run the following commands.
git config --global user.name "Your Name"
git config --global user.email "you@example.com"This section covers the most common Git commands you’ll use at IC Hack. You don’t need to know everything—just enough to collaborate smoothly.
To start off, you can create a new repository on GitHub and share it with your teammates.
-
Go onto the main page of the repository and click
<> Code. Then, copy the url for the repository.
-
Open Git Bash.
-
Make sure the terminal's current working directory is the location you want the cloned repository to exist in.
-
Type
git clone, and then paste the URL you copied earlier.git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
-
Press Enter to create your local clone.
$ git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY > Cloning into `Spoon-Knife`... > remote: Counting objects: 10, done. > remote: Compressing objects: 100% (8/8), done. > remove: Total 10 (delta 1), reused 10 (delta 1) > Unpacking objects: 100% (10/10), done.
After you have cloned the repo, make some changes. You can then stage them using the command:
git add .Then, you can run
git commit -m "example commit message"which will save your changes locally.
If you do not want to commit all your changes,
git add [filename]can be used selectively to add only files you are interested in. You can also add certain file extensions and folders to a .gitignore file to ensure they are never tracked. Place the .gitignore file in the root of your repo. You may also want to refer to the documentation and template .gitignore files.
Here is an example stolen from the Git docs:
# ignore all .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in any directory named build
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdfYou can use
git statusat any time to check the state of your working directory and see which files are modified, staged, or untracked.
Before working with a remote repository, it’s important to ensure that your local clone is up to date.
Running
git pullupdates your current local branch by fetching and merging the latest commits from the corresponding remote branch on GitHub.
After you have implemented a feature or fixed a bug, you should upload your local commits to the remote repository.
Running
git pushsends all commits from your local branch to the corresponding branch on the remote.
Tip
Make sure to run git pull everytime before you run git push to ensure your local branch is up to date and most importantly to avoid merge conflicts!
Since you will likely be using an IDE for your IC Hack project, you can utilise the inbuilt version control tools to make commiting changes simple.
For VSCode, any changes you make since the last commit will be shown in the left hand panel by clicking on the graph symbol.
You can stage a modified file by pressing the + as you hover over it. You can also preview the changes by clicking on the file in that panel, and even revert the changes!
To commit your staged changes, write your commit message at the top of the panel and click Commit.
Once committed, that Commit button becomes Sync Changes. This automatically pulls then pushes your changes!
![TIP] You can also click the drop-down arrow next to the
Commitbutton if you would like toCommit and SyncorCommit and Pushtogether!
Branches allow you to work on new features or bug fixes without affecting the main codebase. This makes collaboration safer and more organised.
To see all available branches, you can run:
git branchBranch names will be shown and the one you are 'checking out' right now will be highlighted with an asterisk (*).
To create and switch to a new branch, run
git checkout -b branch-nameto create a new branch and immediately check it out.
Warning
This command creates a new branch that originates at the currently checked-out branch. Ensure that you are on the right branch.
Alternatively, specify the source
git checkout source-branch
git checkout -b branch-nameIf you only want to create a new branch without switching to it, instead run
git branch branch-nameIf you want to switch to any existing branch, run
git checkout branch-nameSince we are using Git to work collaboratively, it is useful to know how to create branches on the remote. This is just your branch being published to GitHub (most likely!), so your teammates can see your work and contribute alongside.
Once you have created your local branch, simply run
git push -u origin branch-nameIf you already have a remote branch, that you want to clone as a local branch, run
git fetch
git checkout remote-branch-nameTo easily see the list of remote branches, run
git fetch
git branch -rSometimes Git might block your branch checkout if you have uncommitted changes that would be overwritten and shows
error: Your local changes to the following files would be overwritten by checkoutIf you want to switch branches and receive this error, you can:
This is straightforward as you just commit all your changes to remote.
git add .
git commit -m "your commit message"If you don't want to commit your changes yet but still want to save your progress, you can stash your change. Stashing means git saves your changes on a stack and temporally revert all the changes so that you can switch branches or do other changes safely.
git stash #This will save your progress
git checkout branch-name
git stash pop #If you want to retrieve your progress, you can pop it out from the stackIf you want to discard all the changes you made, you can:
git reset --hardOnce your work on a branch is complete and tested, you can merge it back into another branch (usually main or master).
git checkout main # First, switch to the branch you want to merge into
git pull # Make sure it is up to date before merging
git merge feature-branch-name # Then merge your feature branch into mainIf there are no conflicts, Git will automatically complete the merge. If conflicts occur, Git will prompt you to resolve them manually before completing the merge. If you are using any IDE like VS code, they usually provide a conflict editor.
After all conflicts are resolved, your branch will now be successfully merged into main.
After a successful merge, you can optionally delete the feature branch:
git branch -d feature-branch-nameAlternatively, you can use Pull Requests on GitHub to merge branches into main.
This is considered best practice, as it allows teammates to review the changes, provide feedback, and approve the merge before it is completed.
Tip
Try to keep branches small, ideally one branch should be one feature!
Large branches can cause serious merge conflicts!
In the very unfortunate scenario that you have merge conflicts that Git can't automatically resolve, it is up to you to fix it!
This is what you could see in a file with a merge conflict:
Hello World
<<<<<<< HEAD
Feature B
=======
Feature A
>>>>>>> branch-aThe text between HEAD and ======= denote the code on your branch. The text between ======= and branch-a are the incoming changes.
To resolve, you must remove all of the below characters in a text editor
<<<<<<< HEAD
=======
>>>>>>> branch-aAnd you must also resolve the conflict as you see fit! This typically involves either keeping your change, the incoming change, both, or a mix of both.
This process can be made much simpler through the use of GitHub's UI, which will highlight these conflicts.
Many of you will be using VSCode as your IDE (or text editor, whatever...) of choice.
You will see the above when you open a file with a current merge conflict. You can press the buttons above the conflict to quickly resolve conflicts on an individual basis, or across an entire file.
To finalise the resolution of a merge conflict, you must commit all the files whose merge conflicts you have resolved.
If you have made serious mistakes since the last commit, you can run the following to reset a single file to the version that was last committed
git restore <file> For more serious mistakes, you may want to reset your whole branch to the last commit made
git reset --hard If you want to change the commit message of the previous change, run
git commit --amendIf you forgot to add a file to a commit, just run
git add <file>
git commit --amendDon't like the changes made in a specific commit? Run
git revert <commit>The commit is a commit hash, a unique identifier for a commit. These can be found by running
git logor by copying the commit hash from the GitHub website.
This prints the entire history of that branch.
Important
The full history may be truncated at first. If you see : at the bottom of the output, press Enter to get the next line. You can press q at any time to leave this view and get back to your terminal.
One entry in the log could look something like:
commit 8d0fae1dc9da67058f27e86ee4e2b3f7c474a3fb (origin/git-github)
Author: Timofey Kolesnichenko <tk1124@ic.ac.uk>
Date: Fri Jan 9 14:01:07 2026 +0000
Fix: Cleanup some of the formatting and fix typos.where the 8d0fae1... is the commit hash.
Tip
Git is smart! You don't need the full commit hash in order to reference the commit. The first 7 characters are typically sufficient. You may need an 8th or 9th if there happen to be clashes!
Important
git revert <commit> does not delete any history or the changes made.
This simply creates a new commit that undoes the changes made in commit <commit>
Want to completely remove a commit but keep the changes?
git reset --soft HEAD~1In fact, you can remove the previous N commits using
git reset --soft HEAD~NAll the changes made in those commits will still be present as local, unstaged changes.
Once you are happy, you need to push your changes to remote so your teammates can be on the same page.
Since the above actions are destructive (apart from revert), you will need to use
git push --forceWarning
Ensure your teammates do not push any changes while you are force-pushing!
Important
For your teammates to see the changes you push, they must pull!
Tip
The websites linked below have information on how to deal with practically any issue within Git.
A Pull Request (PR) is a way to propose changes to a repository and request that those changes be reviewed and merged into another branch (usually main).
In IC Hack or other team projects, it is recommended to use PR instead of git-merge for merging branches. PR can allow your teammates to quickly review changes and catch bugs early, which can save you time to debug later.
- On GitHub, navigate to the homepage of the repository.
- In the "Branch" menu, choose the branch that contains your commits.

- Above the list of files, in the yellow banner, click
Compare & pull requestto create a pull request for the associated branch.
- Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in.
- Come up with a title and description for your pull request.
After your teammates have reviewed your PR, you should then be able to successfully merge it to main.
An Issue is used to track tasks, bugs, feature requests, or discussions related to a repository.
Although IC Hack projects generally have a shorter timeline, GitHub issues can still be useful as a TODO list or for group discussion about a new feature.
Creating this type of issue can record your brainstroming process, which will be helpful when writing your pitches or explaining your thinking process to the judges.
-
On GitHub, navigate to the main page of the repository.
-
Click
New issue. -
Enter a clear and descriptive title.
-
Use the description to explain:
-
What needs to be done, fixed, or discussed
-
Any relevant context or ideas
-
-
(Optional) Assign the Issue to a teammate and add labels such as bug, feature, or task.
-
Click
Submit new issue.
Although this sounds like a hassle, writing conventional commit messages is actually very useful when working in a team. Conventional commit messages help your teammates understand what changed in that commit, quickly. This will be helpful if you want to go back to a specific commit or ask your teammates about a change in a commit they did.
A good conventional commit message should look like this:
<type>[optional scope]: <description>
Co-authored-by: AAA <ic@hack.com>
Co-authored-by: BBB <hack@ic.com>
Some common types are fix: and feat:, which representing fixing a bug and introduce a new feature respectively. Some other types are build:, chore:, ci:, docs:, style:, refactor:, perf:, test:, and others.
Always commit with small changes or a single feature. When commiting with a lot of features or changes, it can be hard to debug if just one of those changes causes an error.
A bad example:
feat: login, fix tests, formatting, random cleanupIn this example we included a lot of features in different scopes. This will make this commit hard to maintain and debug if we are trying to undo or fix one of the features.
A better example:
feat(login): add email validation
fix(login): prevent crash on empty password
style(login): run formatterIn this example, we have split the changes into small commits so it would be easier to review and revert.
Most teams should have an "always deployable" main branch and short-lived branches that will be merged into main once finished.
main → always deployable
feature/* → short-lived branchesYour team could also establish some rules to maintain branching:
- Never commit directly to
main - Merge via Pull Requests
- Delete branches after merge
- dangitgit and Oh Shit, Git!?! if you need to fix something that's gone terribly wrong.
- Learn Git Branching for a visual gamified way to learn Git.
- Setting up an SSH key to make authentication easier when pushing commits.
- Conventional commits for a detailed explaination on writing good conventional commit messages.



