Introductory Notes on Bash, Git, and GitHub
Introductory Notes on Bash, Git, and GitHub
For Final-Year Undergraduate Software Engineering Students- Adara Institute
As you prepare to transition from academic projects to professional software engineering roles,
mastering core development tools is essential. Employers expect fluency in the command line,
disciplined use of version control, and experience collaborating via platforms like GitHub. This guide
introduces Bash, Git, and GitHub—not just as tools, but as foundational practices that define modern
software engineering workflows.
These skills are critical for:
Building and deploying applications in cloud and containerized environments
Collaborating effectively in agile teams
Maintaining clean, auditable, and reproducible codebases
Showcasing your work through a professional engineering portfolio
I - Bash: The Software Engineer’s Command-Line Foundation
What is Bash?
Bash (Bourne Again SHell) is the default command-line interpreter (shell) for most Linux distributions
and macOS. It allows users to interact with the operating system by typing text-based commands. In
Windows, Bash is available via Windows Subsystem for Linux (WSL).
1. Why Learn Bash?
Automation: Script repetitive tasks (builds, tests, deployments).
DevOps & Cloud: Essential for Docker, Kubernetes, CI/CD pipelines, and cloud CLI tools (AWS,
GCP).
System Administration: Manage files, processes, permissions, and services.
Professional Expectation: Industry-standard skill for software engineers, SREs, and data
scientists.
Reproducibility: Scripted workflows are transparent and repeatable—key for research and
production.
💡 Note: Bash is not just a tool—it’s a programming language. You can write full programs
(scripts) with variables, loops, conditionals, and functions.
2. Getting Started: The Terminal Basics
Opening the Terminal
Linux/macOS: Ctrl + Alt + T (Linux), Cmd + Space → "Terminal" (macOS)
Windows (WSL): Install WSL, then open "Ubuntu" or your chosen distro from Start Menu.
Your First Commands
Command Description
pwd Print Working Directory — shows your current path
ls List files and folders in current directory
cd <directory> Change Directory
cd ~ or just cd Go to your home directory ( /home/username or /Users/username )
cd / Go to the root directory of the filesystem
cd .. Move up one level (parent directory)
cd - Switch back to the previous directory
📌 Path Types:
Absolute path: Starts from root ( /home/user/project )
Relative path: Starts from current location ( ./src , ../docs )
Navigating Windows Drives in WSL
In WSL, Windows drives are mounted under /mnt/ :
`cd /mnt/c # Access C: drive`
`cd /mnt/d # Access D: drive`
⚠️ Always navigate from your Linux home ( ~ ) before accessing /mnt/ to avoid confusion.
3. File and Directory Management
Listing Files
ls # Basic list
ls -l # Long format (permissions, size, date)
ls -a # Show **all** files, including hidden ones (start with `.`)
ls -la # Combine both
ls *.py # List only Python files
Creating Files and Directories
mkdir project # Create a directory
mkdir -p src/tests/utils # Create nested directories (-p = parents)
touch app.py # Create an empty file
touch report.csv data.json # Create multiple files
💡 Why touch ?
It updates a file’s timestamp if it exists, or creates it if it doesn’t. Essential for build systems.
Viewing and Editing Files
cat file.txt # Print entire file
less file.txt # Scroll through large files (press q to quit)
head -n 10 file.log # Show first 10 lines
tail -n 5 file.log # Show last 5 lines
vi script.sh # Simple terminal-based text editor`
Copying, Moving, and Deleting
cp file.txt backup/ # Copy file to directory
cp -r project/ backup/ # Copy directory recursively (-r)
mv old.py new.py # Rename or move file
mv *.log logs/ # Move all .log files
rm temp.txt # Delete a file
rmdir empty_dir/ # Delete empty directory
rm -rf node_modules/ # Force-delete directory and contents
⚠️ Danger Zone:
rm -rf / or rm -rf ~ can destroy your system. Always double-check paths!
4. File Permissions: The Core Security Model (Enhanced)
In Linux and other Unix-like systems, file permissions form the bedrock of system security, access
control, and multi-user collaboration. Unlike graphical operating systems that often hide these
mechanisms, Linux exposes them transparently—giving developers and administrators fine-grained
control over who can read, modify, or execute any file or directory.
Understanding permissions is not just about running chmod ; it’s about designing secure, maintainable,
and collaborative systems. This section goes beyond syntax to explain how permissions work, why
they matter, and how to apply them correctly in real-world software engineering contexts.
4.1 The Three Fundamental Permission Types
Every file and directory in Linux has three basic permission types, each serving a distinct purpose:
Symbol Name On Files On Directories
r Read View or copy file contents List contents ( ls )
Modify, overwrite, or delete Create, rename, or delete files inside
w Write
the file the directory
Run the file as a program Enter the directory ( cd ), access files
x Execute
or script inside
🔥 Critical Insight:
Directory permissions are gatekeepers.
Without x , you cannot access anything inside—even if you know the exact filename.
Without r , you cannot list contents, but you can still access a file if you know its name
and have x .
Without w , you cannot add or remove files—but you can still modify existing files if you
have write permission on the file itself.
Example: Permission Behavior in Practice
Suppose you have a directory secret/ with permissions --x------ (only owner can enter):
$ ls -ld secret/
d--x------ 2 alice alice 4096 Jun 10 secret/
$ ls secret/
ls: cannot open directory 'secret/': Permission denied # No 'r'
$ cat secret/password.txt
cat: secret/password.txt: Permission denied # But wait—why?
$ # However, if you somehow know the filename AND the file has read
permission:
$ # You still can't access it because you lack 'x' on the parent!
Now change to r-x------ :
$ ls secret/
password.txt # Now you can list it
$ cat secret/password.txt
supersecret123 # And read it (if the file itself is readable)
💡 Takeaway: For directories, x is required to traverse, r to list, and w to modify contents.
4.2 The Three User Classes: Owner, Group, Others
Permissions are applied to three distinct categories of users:
Class Abbreviation Description
User u The owner of the file (set via chown )
Group g All users who are members of the file’s group (set via chgrp )
Others o Everyone else on the system
This model enables role-based access control without complex policies:
The owner (e.g., a developer) has full control.
The group (e.g., dev-team ) has collaborative access.
Others (e.g., system users, guests) have restricted or no access.
Real-World Analogy
Think of a shared office:
Owner = The employee who owns the desk (can lock/unlock, rearrange).
Group = Team members with a key to the shared cabinet.
Others = Visitors who can only look through the glass door ( r ), but not enter ( x ) or touch anything
( w ).
4.3 Viewing Permissions with ls -l
The ls -l command reveals the full permission model:
$ ls -l /etc/hosts
-rw-r--r-- 1 root root 220 Jan 15 10:30 /etc/hosts
Breakdown:
1st character: File type ( - = regular file, d = directory, l = symlink)
Next 9 characters: Permissions in triplets → user | group | others
rw- → owner: read + write
r-- → group: read only
r-- → others: read only
Links: 1 (number of hard links)
Owner: root
Group: root
Size: 220 bytes
Timestamp: Jan 15 10:30
Filename: /etc/hosts
📌 Pro Tip: Use stat filename for even more detail (inode, device, access times).
4.4 Numeric (Octal) vs. Symbolic Permission Notation
Linux supports two ways to represent permissions: symbolic (human-readable) and numeric (compact,
script-friendly).
4.4.1 Numeric (Octal) Notation
Each permission triplet is converted to a number:
Permission Binary Value
--- 000 0
--x 001 1
-w- 010 2
-wx 011 3
r-- 100 4
r-x 101 5
rw- 110 6
rwx 111 7
So:
755 = rwxr-xr-x → Owner: full, Group/Others: read + execute
644 = rw-r--r-- → Owner: read/write, Others: read-only
700 = rwx------ → Private to owner
600 = rw------- → Private file (no execute)
💡 Why octal?
Each digit represents 3 bits (2³ = 8 values → 0–7). Three digits = 9 bits = full permission set.
4.4.2 Symbolic Notation
More intuitive for interactive use:
u = user, g = group, o = others, a = all
Operators: + (add), - (remove), = (set exactly)
Examples:
chmod u+x script.sh # Add execute for owner
chmod g-w config.yaml # Remove write for group
chmod o= file.txt # Remove all permissions for others
chmod a=r README.md # Set all to read-only
✅ Best Practice:
Use symbolic mode for clarity in scripts and documentation.
Use numeric mode in automation (e.g., Dockerfiles, CI pipelines) for brevity.
4.5 Changing Permissions: The chmod Command
Syntax
chmod [options] <mode> <file...>
Common Patterns
Use Case Command Numeric Equivalent
Make script executable chmod u+x deploy.sh chmod 755 deploy.sh
Private config file chmod 600 .env —
Shared team directory chmod 775 /projects/app —
Web-accessible assets chmod 644 *.css *.js —
Recursive Changes
chmod -R 755 /var/www/html # Apply to all files and subdirs
⚠️ Warning: Recursive chmod can break security!
Directories need x , files usually don’t. Consider:
find /path -type d -exec chmod 755 {} \; # Directories
find /path -type f -exec chmod 644 {} \; # Files
4.6 Default Permissions: The umask
When you create a file or directory, its permissions are not 777 or 666 by default. Instead, the system
applies a umask (user file-creation mask) to restrict permissions.
How umask Works
Default file permissions: 666 (rw-rw-rw-)
Default directory permissions: 777 (rwxrwxrwx)
umask subtracts permissions (in octal)
Example:
$ umask
0022
# File: 666 - 022 = 644 → rw-r--r--
# Dir: 777 - 022 = 755 → rwxr-xr-x
Setting umask
Temporary: umask 002 → group-collaborative mode ( 664 / 775 )
Permanent: Add to ~/.bashrc or /etc/profile
💡 Team Tip: In shared environments, set umask 002 so new files are group-writable.
4.7 Permission Best Practices for Software Engineers
Resource Recommended Permissions Rationale
Readable by all, writable only by
Source code files 644
owner
Executable by owner, readable by
Shell/Python scripts 755
team
Private keys (SSH, Only owner can read—SSH
600
TLS) enforces this
Web root directories 755 Web server must traverse
Web config files 640 or 600 Prevent public exposure of secrets
644 (or 664 if rotated by Appendable by app, readable by
Log files
group) admins
Temporary files 600 Avoid leaking sensitive data
🛡️ Security Principle:
Never use 777 —it grants full access to everyone, including attackers.
If a service “needs” 777 , redesign the architecture (e.g., use proper ownership or ACLs).
4.8 Troubleshooting Permission Issues
Common Symptoms & Fixes
Diagnostic
Symptom Likely Cause Fix
Command
Permission
Missing x on
denied on cd ls -ld dir chmod +x dir
dir
directory
Can’t list directory Missing r on
ls -ld dir chmod g+r dir
contents directory
Can’t run script File on noexec mount | grep
Move to /home or /opt
despite rwx mount (e.g., /tmp ) noexec
SSH ignores Permissions too ssh -v chmod 600
private key open user@host ~/.ssh/id_rsa
ps aux | grep
Web server can’t File not readable by chgrp www-data file;
nginx → check
read file www-data user chmod 640 file
user
5. Managing Users in Linux
In Linux, users are fundamental to system security, resource isolation, and access control. Every
process runs under a user identity, and every file is owned by a user (and a group). Understanding how
to create, configure, and manage users is essential for:
Securing applications and services
Setting up development and production environments
Implementing least-privilege principles
Managing team access on shared servers
Working with containers (Docker, Kubernetes) and cloud infrastructure
This guide covers user management from foundational concepts to professional best practices.
5.1. What Is a User in Linux?
A user is a logical identity with:
A unique User ID (UID) (numeric)
A username (human-readable alias for the UID)
A home directory (e.g., /home/alice )
A default login shell (e.g., /bin/bash )
Optional: full name, email, password expiry, etc.
💡 Key Insight:
The kernel uses UIDs, not usernames. Usernames are just labels stored in /etc/passwd .
5.2 Types of Users
Type UID Range Purpose
Root 0 Superuser with unrestricted access
System users 1–999 (or 1–499 ) Run daemons/services (e.g., www-data , mysql )
Regular users 1000+ Human users (developers, admins, etc.)
🛡️ Security Note:
Never run applications as root . Always create dedicated system users (e.g., app-user ) with
minimal privileges.
5.3. Core User Management Files
Linux stores user and authentication data in plain-text (or shadowed) files:
File Purpose Permissions
User account metadata (username, UID, 644 (readable by
/etc/passwd
GID, home, shell) all)
/etc/shadow Encrypted passwords and password policies 600 (root-only)
/etc/group Group definitions and member lists 644
/etc/gshadow Secure group password info (rarely used) 600
Default settings for new users (UID range,
/etc/login.defs —
password expiry, etc.)
/etc/default/useradd Default values for the useradd command —
Example: /etc/passwd Entry
alice:x:1001:1001:Alice Smith,,,:/home/alice:/bin/bash
Fields (colon-separated):
1. Username: alice
2. Password placeholder: x → actual hash in /etc/shadow
3. UID: 1001
4. Primary GID: 1001 (usually matches UID)
5. GECOS field: Full name, office, phone (optional)
6. Home directory: /home/alice
7. Login shell: /bin/bash
🔍 View your own entry:
getent passwd $USER
5.4. Adding Users
5.4.1 Using adduser (Debian/Ubuntu – Recommended)
The adduser command is a user-friendly Perl script that:
Creates home directory
Copies skeleton files from /etc/skel
Prompts for password and user info
Creates a primary group with the same name
sudo adduser developer
Interactive prompts:
Adding user `developer' ...
Adding new group `developer' (1001) ...
Adding new user `developer' (1001) with group `developer' ...
Creating home directory `/home/developer' ...
Copying files from `/etc/skel' ...
New password: ********
Retype new password: ********
passwd: password updated successfully
Changing the user information for developer
Enter the new value, or press ENTER for the default
Full Name []: Dev Team Member
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] Y
✅ Best for: Interactive setup, human users.
5.4.2 Using useradd (All Distros – Scriptable)
The useradd command is a low-level utility with fine-grained control. It does not prompt interactively.
Basic Usage
sudo useradd -m -s /bin/bash -c "Backend Developer" backend-dev
sudo passwd backend-dev # Set password separately
Common Options
Option Purpose
-m Create home directory ( /home/username )
-d /path Specify custom home directory
-s /bin/shell Set login shell
-c "Comment" Set GECOS (full name, description)
-g group Assign primary group (by name or GID)
-G group1,group2 Add to supplementary groups
-u UID Specify custom UID
-r Create a system user (no home, no password, UID < 1000)
Example: Create a System User for a Service
sudo useradd -r -s /usr/sbin/nologin -M app-service
-r : System user
-s /usr/sbin/nologin : Prevents shell login
-M : Do not create home directory
✅ Best for: Automation, Dockerfiles, CI/CD scripts.
5.6 Managing Existing Users
5.6.1 Modifying User Accounts: usermod
Change user properties after creation:
Task Command
Change shell sudo usermod -s /bin/zsh alice
Add to supplementary groups sudo usermod -aG sudo,docker alice
Lock account (disable login) sudo usermod -L alice
Unlock account sudo usermod -U alice
Change home directory sudo usermod -d /new/home/alice -m alice
Task Command
Change UID sudo usermod -u 2000 alice
⚠️ Critical:
Use -aG (append to groups). Without -a , usermod -G removes the user from all other
groups!
5.6.2 Setting/Changing Passwords: passwd
# Change your own password
passwd
# Change another user's password (as root)
sudo passwd alice
# Expire password (forces change on next login)
sudo passwd -e alice
# Lock password (same as usermod -L)
sudo passwd -l alice
🔐 Security Tip:
For service accounts, disable passwords and use SSH keys or API tokens instead.
5.6.3 Viewing User Information
Command Purpose
id alice Show UID, GID, and all groups
groups alice List supplementary groups
getent passwd alice Show /etc/passwd entry
finger alice (If installed) Show user info, login status
last alice Show login history
5.6.4 Deleting Users: userdel
# Remove user but keep home directory
sudo userdel alice
# Remove user AND home directory
sudo userdel -r alice
# Remove user, home, and mail spool
sudo userdel -r -f alice
⚠️ Warning:
-r permanently deletes the home directory. Ensure backups exist!
5.6 Special Accounts and Security Practices
5.6.1 The root Account
UID 0 , full system access.
Never use for daily tasks.
Prefer sudo for privilege escalation.
5.6.2 Service Accounts (System Users)
Created with useradd -r
No password, no home, no shell login
Used to run daemons (e.g., nginx , postgres )
Example: Secure web app user
sudo useradd -r -s /usr/sbin/nologin -M webapp
sudo chown -R webapp:webapp /opt/myapp
sudo -u webapp /opt/myapp/start.sh # Run as webapp
5.6.3 Disabling Shell Access
For users who only need SFTP or API access:
sudo usermod -s /usr/sbin/nologin username
# or
sudo usermod -s /bin/false username
✅ Both prevent interactive shell login while allowing other services.
5.7. Best Practices for Software Engineers
Practice Why It Matters
Never run apps as root Limits blast radius of exploits
Use dedicated service users Isolates processes and data
Prefer groups over individual permissions Simplifies team access management
Disable passwords for service accounts Reduces attack surface
Practice Why It Matters
Set strong password policies Enforce via /etc/login.defs or PAM
Audit user accounts regularly Remove inactive or unused accounts
Use SSH keys instead of passwords More secure, scriptable, no password expiry
Example: Secure Development Server Setup
# Create team group
sudo groupadd dev-team
# Add developers to group
sudo usermod -aG dev-team alice
sudo usermod -aG dev-team bob
# Create shared project directory
sudo mkdir /projects/backend
sudo chgrp dev-team /projects/backend
sudo chmod 2775 /projects/backend # SGID + rwx for group
# Create service user for deployment
sudo useradd -r -s /usr/sbin/nologin -M deploy-bot
5.8 Integration with Modern Workflows
Docker
In Dockerfiles, avoid running as root:
RUN adduser --disabled-password --gecos '' appuser
USER appuser
Cloud (AWS, GCP)
Linux users map to IAM roles or service accounts.
Use cloud-init to provision users on VM launch.
Configuration Management (Ansible, Puppet)
Automate user creation:
# Ansible example
- name: Create developer user
user:
name: devops
groups: sudo,docker
shell: /bin/bash
generate_ssh_key: yes
5.9 Common Pitfalls & Troubleshooting
Issue Diagnosis Fix
Shell set to
User can’t log in usermod -s /bin/bash user
/usr/sbin/nologin
Permission denied in usermod -aG project-group
User not in correct group
shared dir user + relogin
Home directory
Forgot -m in useradd mkhomedir_helper username
missing
sudo not working User not in sudo group usermod -aG sudo username
Password not passwd -u username , chage -I
Account locked or expired
accepted -1 username
🔁 Remember: Group membership changes require logout/login or newgrp groupname .
Conclusion
User management is not just system administration—it’s a core software engineering skill. Whether
you’re deploying a microservice, securing a CI pipeline, or setting up a team server, principled user
management ensures:
Security through least privilege
Isolation between services and teams
Reproducibility in automated environments
Master these concepts, and you’ll design systems that are not only functional but secure by default.
🚀 Challenge:
Write a Bash script that:
1. Creates a system user for a new service
2. Sets up a dedicated home-like directory in /opt
3. Adds the user to a logging group
4. Outputs a sudo command to run the service securely
Your future DevOps team will thank you.
6. Environment and Variables
Environment Variables
Store configuration values (e.g., PATH , HOME ):
echo $HOME # Print value of HOME
echo $PATH # Print executable search paths
export MY_VAR="hello" # Create a new environment variable (lasts for session)
The PATH Variable
A list of directories where the shell looks for executable commands.
Add a custom script directory:
export PATH=$PATH:/home/user/bin
Shell vs. Environment Variables
Shell variable: name="value" — only in current shell
Environment variable: export name="value" — passed to child processes
7. Input/Output Redirection and Pipes
Redirection
> : Redirect output to a file (overwrite)
>> : Redirect output to a file (append)
< : Use file as input
Examples:
ls > filelist.txt # Save directory listing to file
echo "Hello" >> log.txt # Append to log
sort < data.txt # Sort contents of data.txt
Pipes ( | )
Chain commands: output of one becomes input of next.
ls -l | grep ".py" # List only Python files
ps aux | grep nginx # Find nginx processes
cat access.log | cut -d' ' -f1 | sort | uniq -c # Count unique IPs
💡 Power Combo:
history | grep git → find all Git commands you’ve run.
12. From Student to Professional: Real-World Use Cases
Scenario Bash Application
Automated Testing for test in tests/*.py; do python "$test"; done
Log Analysis grep "ERROR" app.log | awk '{print $4}' | sort | uniq -c
Deployment Script Build → Test → SCP to server → Restart service
Data Pipeline Download → Clean → Transform → Load (all in one script)
CI/CD Integration GitHub Actions, GitLab CI often run Bash scripts
II – Git: Professional Version Control (Beginner-Friendly Guide)
1. What Is Git? Why Should You Care?
Git is a version control system—a tool that helps you track every change you make to your code over
time. Think of it like "undo" on steroids, but much more powerful:
Save snapshots of your project (called commits)
Go back to any previous version
Work on new features without breaking your main code
Collaborate with teammates safely
💡 Real-World Analogy:
Git is like a time machine for your code.
Commit = Take a photo of your project at a moment in time
Branch = Work on a copy of your project without affecting the original
Merge = Bring your copy back into the main project when it’s ready
In industry, every professional software team uses Git. Not knowing Git is like trying to drive without
a license.
2. Core Concepts – Explained Simply
📁 Repository (Repo)
A repository is just a project folder that Git is watching. Once you run git init , Git starts
recording every change you make.
Local repo: The copy on your computer
Remote repo: The shared copy on GitHub, GitLab, or Bitbucket
🌐 Remote repos let you:
Share code with teammates
Back up your work
Show your portfolio to employers
🧱 The Three Areas of Git
Git works with three main areas:
Area What It Is What You Do There
Working Your actual project files (what you see in
Edit, create, delete files
Directory Finder/Explorer)
A "preview" of what will go into your next Choose which changes to
Staging Area
commit save
The hidden history folder (stores all your Git manages this
Repository (.git)
commits) automatically
🔍 Example:
You fix a bug and add a new feature in one session.
Use the staging area to commit the bug fix first
Then commit the new feature separately
→ Two clean, logical commits instead of one messy one!
3. Setting Up Git – Your First Steps
Step 1: Tell Git Who You Are
Git needs your name and email to label your commits. Do this once on your computer:
git config --global user.name "Your Full Name"
git config --global user.email "
[email protected]"
⚠️ Important:
Use the same email you use on GitHub—otherwise your commits won’t link to your profile!
Step 2: Set Helpful Defaults (Optional but Recommended)
# Make 'main' the default branch name (modern standard)
git config --global init.defaultBranch main
# Make 'git push' easier
git config --global push.autoSetupRemote true
4. Your First Git Project – Step by Step
🛠️ Create a New Project
# 1. Make a new folder (never use your home/desktop!)
mkdir my-first-app
cd my-first-app
# 2. Turn it into a Git repo
git init
# 3. Create a file
echo "# My First App" > README.md
# 4. Stage the file (add to preview)
git add README.md
# 5. Save the snapshot (commit)
git commit -m "docs: add README file"
💡 What just happened?
You took your first photo of your project! Git saved the state of README.md forever.
5. The Daily Git Workflow
🔄 Basic Cycle: Edit → Stage → Commit
1. Edit files in your working directory
2. Stage changes you want to save:
git add filename.txt # Stage one file
git add . # Stage all changed files
3. Commit the staged changes:
git commit -m "feat: add user login button"
🔍 Check Your Status
Always check what’s going on:
git status
This tells you:
Which files are modified
Which are staged
If you’re ahead/behind the remote
6. Viewing History – Your Project’s Diary
See All Commits
git log # Full history (press 'q' to quit)
git log --oneline # Compact view (one line per commit)
Example output:
a1b2c3d (HEAD -> main) feat: add login button
e4f5g6h docs: add README
🔍 HEAD = Where you are right now in history
main = Your main branch name
7. Fixing Mistakes – Safely!
🛑 Undoing Changes (Before Commit)
Discard changes in a file:
git restore filename.txt
Unstage a file (keep changes):
git restore --staged filename.txt
↩️ Undoing Commits (After Commit)
Option 1: git revert → Safe for Team Projects
Creates a new commit that cancels an old one
Never deletes history—safe for shared code
git log --oneline # Find the bad commit ID (e.g., a1b2c3d)
git revert a1b2c3d # Creates a new "undo" commit
✅ Use this when:
You pushed code to GitHub and need to fix a bug in main .
Option 2: git reset → Only for Your Local Work
Rewrites history—dangerous if others have seen your commits
Three levels of "undo":
Command What It Does When to Use
git reset --soft Undo last commit, keep changes
Fix commit message
HEAD~1 staged
Command What It Does When to Use
Undo commit, keep changes Split commit into smaller
git reset HEAD~1
unstaged ones
git reset --hard Delete last commit and all Emergency cleanup (last
HEAD~1 changes resort!)
⚠️ Golden Rule:
Never use reset on commits you’ve pushed to GitHub!
It will break your teammates’ repos.
8. Branches – Your Safety Net for New Features
🌿 What Is a Branch?
A branch is a parallel version of your project.
main branch: Your stable, working code
Feature branch: A playground to try new things
💡 Why branch?
You can break everything in your feature branch—and main stays safe!
🧪 Branching Workflow
1. Start from main :
git checkout main
git pull origin main # Get latest changes
2. Create and switch to a new branch:
git checkout -b feature/user-profile
# OR (modern way)
git switch -c feature/user-profile
3. Work, commit, and push:
# ... make changes ...
git add .
git commit -m "feat: add profile page"
git push -u origin feature/user-profile
4. When done, merge into main (via Pull Request on GitHub)
🗑️ Clean Up After Merging
git checkout main
git pull origin main # Get the merged code
git branch -d feature/user-profile # Delete local branch
git push origin --delete feature/user-profile # Delete remote branch
⚠️ Critical Tip:
You must make at least one commit before creating branches.
An empty repo has no main branch—your first branch becomes the default!
9. Writing Good Commit Messages
Your commit messages are notes to your future self and teammates. Bad messages cause
confusion; good ones save hours.
📝 The Standard Format (Conventional Commits)
<type>(<scope>): <short summary>
<optional longer description>
🏷️ Common Types (Use These!)
Type When to Use Example
feat Adding a new feature feat(auth): add Google login
fix Fixing a bug fix(api): handle empty user input
docs Documentation only docs: update installation guide
style Formatting (no code change) style: format code with Prettier
refactor Rewriting code (same behavior) refactor: clean up user service
test Adding tests test: add login validation tests
chore Maintenance (deps, config) chore: upgrade React to v18
✅ Good vs. Bad Examples
❌ "fixed stuff"
✅ "fix(login): prevent null pointer on empty email"
❌ "updated code"
✅ "feat(profile): add avatar upload"
💡 Pro Tips:
Keep the first line under 50 characters
Use imperative mood: "Add" not "Added"
Reference issue numbers: fix(#123): resolve timeout
10. Merge Conflicts – Don’t Panic!
❓ What Is a Conflict?
When Git can’t automatically combine changes because two people edited the same lines.
🔧 How to Fix It
1. Git will mark the conflicted file:
<<<<<<< HEAD
console.log("old code");
=======
console.log("new code");
>>>>>>> feature/login
2. Edit the file to keep what you want (remove the <<<<<<< , ======= , >>>>>>> lines)
3. Stage and commit the fixed file:
git add .
git commit -m "fix: resolve conflict in logger"
🛡️ How to Avoid Conflicts
Pull main often while working on your feature
Keep PRs small (< 400 lines of code)
Talk to teammates if you’re working on the same files
11. How Big Companies Use Git
🏢 Facebook (Meta) – Trunk-Based Development
Only one main branch: main
No long-lived feature branches
Developers:
1. Sync to main multiple times a day
2. Make tiny, frequent commits
3. Use feature flags to hide unfinished work
Why? Avoids massive merge conflicts at scale
🖥️ GitHub Flow (Used by GitHub, Netflix, Shopify)
1. main is always deployable
2. Create a short-lived feature branch
3. Open a Pull Request (PR) for review
4. Merge → Deploy immediately
12. Beginner Checklist – Do This Every Time
✅ Before coding:
git checkout main
git pull origin main
✅ While coding:
Create a feature branch
Commit small, logical changes
Write clear commit messages
✅ Before pushing:
git rebase main (to include latest changes)
Resolve any conflicts
✅ After merging:
Delete your feature branch (local + remote)
**III. GitHub: Your Engineering Portfolio & Collab
1. What Is GitHub? Why Should You Care?
GitHub is a cloud platform that hosts Git repositories and adds powerful collaboration tools. Think of it
as:
Google Docs for code → Multiple people can work together safely
Your engineering résumé → Recruiters check GitHub before interviews
A project showcase → Capstone projects, hackathons, personal apps
💡 Key Insight:
Git = The tool that tracks changes on your computer
GitHub = The website that stores your Git history online and adds teamwork features
In industry, GitHub (or GitLab/Bitbucket) is non-negotiable. Not having a GitHub profile is like
graduating without a portfolio.
2. Creating Your First GitHub Project – Step by Step
🌐 Step 1: Create a Repository on GitHub
1. Go to github.com and sign in
2. Click the + → New repository
3. Fill in:
Repository name: my-first-app
Description: "A simple web app for university project"
Visibility: Public (so recruiters can see it!)
4. ⚠️ Important: DO NOT check:
☐ Add a README file
☐ Add .gitignore
☐ Choose a license
→ This avoids merge conflicts later!
5. Click Create repository
📝 Why skip README/.gitignore?
If you add them on GitHub and locally, Git sees two different histories → merge conflict!
We’ll add them safely in Step 4.
💻 Step 2: Connect Your Local Project to GitHub
In your terminal:
# 1. Create and enter your project folder
mkdir my-first-app
cd my-first-app
# 2. Initialize Git (creates .git folder)
git init
# 3. Create your first file
echo "# My First App" > README.md
# 4. Commit it locally
git add README.md
git commit -m "docs: add initial README"
# 5. Link to GitHub (replace YOUR-USERNAME)
git remote add origin https://github.com/YOUR-USERNAME/my-first-app.git
# 6. Verify the connection
git remote -v
# Should show:
# origin https://github.com/YOUR-USERNAME/my-first-app.git (fetch)
# origin https://github.com/YOUR-USERNAME/my-first-app.git (push)
📤 Step 3: Push Your Code to GitHub
# First push: use -u to set "upstream" tracking
git push -u origin main
🔍 What does -u do?
It remembers that your local main branch connects to GitHub’s main .
After this, you can just type git push and git pull !
You’ll be asked for your GitHub username and password.
⚠️ Important: GitHub no longer accepts passwords!
Use a Personal Access Token (PAT) instead:
1. Go to Settings → Developer settings → Personal access tokens
2. Generate a new token with repo permissions
3. Use this token as your "password"
3. Adding Essential Files the Right Way
Now that your repo is synced, add these via GitHub’s website:
📄 Add a LICENSE
1. On your GitHub repo page, click Add file → Create new file
2. Type exactly: LICENSE (no extension!)
3. GitHub will show: "Choose a license template" → Click it!
4. Select MIT License (most permissive for students)
5. Click Review and commit
💡 Why MIT?
It lets anyone use your code, as long as they give you credit. Perfect for portfolios!
🚫 Add a .gitignore
1. Click Add file → Create new file
2. Type exactly: .gitignore
3. GitHub will suggest templates → Choose Python, Node, etc.
4. Add extra lines if needed (e.g., .env , secrets.txt )
5. Click Commit new file
🛡️ Why .gitignore?
Prevents accidentally committing:
Passwords ( .env )
Build files ( dist/ , __pycache__/ )
OS files ( .DS_Store , Thumbs.db )
4. Daily GitHub Workflow – The Professional Way
🔄 Pulling Changes (Get Latest Code)
git checkout main # Switch to main branch
git pull # Get latest from GitHub
💡 Do this every time you start working!
Ensures you’re building on the latest version.
🌿 Working on a New Feature or Bug Fix
Step 1: Create a Branch
git checkout -b feature/user-login
# OR
git switch -c bugfix/api-timeout
📌 Branch Naming Tips:
feature/... for new functionality
bugfix/... for critical fixes
docs/... for documentation updates
Step 2: Code, Commit, Push
# ... make your changes ...
git add .
git commit -m "feat(auth): add Google OAuth login"
git push -u origin feature/user-login
🔍 What -u does here:
Links your local branch to the remote one. Next time, just git push !
Step 3: Create a Pull Request (PR)
1. Go to your GitHub repo
2. You’ll see: "Your recently pushed branches" → Click Compare & pull request
3. Fill in:
Title: "feat(auth): add Google OAuth login"
Description:
## What this does
- Adds "Login with Google" button
- Stores user profile in database
## How to test
1. Click login button
2. Accept Google permissions
3. Verify user appears in /profile
4. Click Create pull request
💡 Why PRs?
Lets teammates review your code before merging
Runs automated tests (if set up)
Creates a record of changes for future reference
Step 4: After Merge – Clean Up
git checkout main # Switch back to main
git pull # Get the merged code
git branch -d feature/user-login # Delete local branch
🗑️ Delete remote branch (optional but tidy):
git push origin --delete feature/user-login
5. Making Your GitHub Profile Shine
Your GitHub profile is often the first thing recruiters see. Treat it like a portfolio!
✅ Must-Have Elements
Element How to Add Why It Matters
Create a repo named YOUR-
Shows a custom bio, skills, and
Profile README USERNAME.github.io OR YOUR-
projects at the top of your profile
USERNAME
Element How to Add Why It Matters
Pinned On your profile, click Customize your
Highlights your 6 best projects
Repositories pins
Every repo should have a README.md
with:
Shows communication skills
Clear READMEs - Project description
and professionalism
- Screenshots
- Setup instructions
Conventional Use feat: , fix: , docs: in commit Proves you understand industry
Commits messages standards
Work on projects regularly (even small
Public Activity Shows passion and consistency
ones!)
📝 Example README.md Structure
# User Profile Manager
A React app to manage user profiles with Google OAuth.

## Features
- Login with Google
- Edit profile picture
- Dark mode toggle
## Setup
1. `git clone https://github.com/you/profile-manager.git`
2. `npm install`
3. Create `.env` with `GOOGLE_CLIENT_ID=...`
4. `npm start`
## Tech Stack
- React, Firebase, Tailwind CSS
6. Common Beginner Mistakes (And How to Avoid Them)
Mistake Why It’s Bad Fix
1. Add to .gitignore
Committing secrets Hackers scan GitHub for
2. Use git rm --cached .env to
( passwords , .env ) these!
remove from history
Working directly on
Breaks production code Always use feature branches
main
Mistake Why It’s Bad Fix
Huge pull requests Hard to review, more Break work into small PRs (< 400
(1000+ lines) bugs lines)
Vague commit messages Impossible to debug Use conventional commits:
("fixed stuff") later fix(login): handle null email
Recruiters can’t Spend 10 minutes writing a clear
Not writing READMEs
understand your project README
🔐 Emergency: Remove a secret you accidentally committed
1. Delete the file locally
2. Add to .gitignore
3. Run:
git rm --cached secret-file.txt
git commit -m "chore: remove secret file"
git push
4. Rotate the secret immediately (assume it’s compromised!)
7. GitHub Features You Should Use
Feature How to Access Why Use It
Tab on your
Issues Track bugs, features, and tasks (like a to-do list)
repo
Tab on your
Projects Kanban boards for planning (To Do / In Progress / Done)
repo
Tab on your Automate tests, builds, and deployments (free for public
Actions
repo repos!)
Tab on your
Discussions Q&A forum for your project (great for open-source)
repo
Sponsors Profile settings Get paid for your open-source work (later in career)
💡 Student Tip:
Enable GitHub Student Developer Pack → Get free credits for AWS, Docker, etc.!
https://education.github.com/pack
8. Final Checklist for GitHub Success
✅ Before pushing code:
.gitignore has all secrets/build files
README explains what the project does
Commit messages follow conventional format
✅ When creating a PR:
Title starts with feat: , fix: , etc.
Description explains what and how to test
Linked to an Issue (if your team uses them)
✅ For your profile:
Pinned your best 3-6 projects
Profile README shows your skills
All repos are public (unless confidential)
9. Remember: GitHub Is Your Career Launchpad
Recruiters spend 6 seconds on your GitHub before deciding to interview you
Open-source contributions (even small docs fixes) prove you can collaborate
Well-documented projects show you think like a professional
🚀 Challenge:
1. Create a new repo with a clear README
2. Add a LICENSE and .gitignore
3. Make a small feature in a branch
4. Create a PR with a professional description
5. Pin it to your profile
This is exactly what you’ll do on your first day as a software engineer. Start now!