Setup and Initialization
To begin working with version control, first verify if Gits available in your environment by running the command:
$ git --version
If the system returns an error indicating the program is missing, install it using the package manager:
$ sudo apt-get install git
Once installed, configure your identity globally so every commit carries attribution:
$ git config --global user.name "Developer Name"
$ git config --global user.email "developer@example.com"
The --global flag applies these settings across all repositories on the current machine. Specific configurations can still be applied per-repository if needed.
Creating a Repository
A repository serves as the core directory managed by Git. Any modification to tracked files is recorded throughout their lifecycle. To initialize a new project, navigate to a target location and create a directory:
$ mkdir web-app
$ cd web-app
Initialize the repository within this directory:
$ git init
Initialized empty Git repository in /path/to/web-app/.git/
This creates a hidden .git directory responsible for tracking metadata. Do not manually alter files within this folder unless absolutely necessary, as corruption may break the repository.
Managing Changes
Tracking modifications involves adding files to the staging area followed by committing them to the database.
# Add a configuration file to staging
$ git add config/settings.yml
# Record changes with a descriptive message
$ git commit -m "feat: initial configuration setup"
The commit message following -m provides context for future audits. Use git status to monitor the state of the workspace at any time. To inspect differences:
git diff: Compares the working tree against the index.git diff --cached: Compares the index against the last commit.git diff HEAD: Compares the working tree against the latest commit.
For example, reviewing changes to settings.yml:
$ git diff HEAD -- settings.yml
diff --git a/settings.yml b/settings.yml
index 46d49bf..9247db6 100644
--- a/settings.yml
+++ b/settings.yml
@@ -1,2 +1,2 @@
-debug: true
+debug: false
To discard local edits completely, revert the file to its last committed state:
$ git checkout -- settings.yml
This restores the file content regardless of whether changes were staged previously.
History Navigation and Reset
View the chronological list of commits starting from the most recent:
$ git log
commit abc123def456...
Author: Developer Name <developer@example.com>
Date: Mon Jan 15 10:00:00 2024
feat: added user auth module
Condense the output for easier reading using the --pretty=oneline option:
$ git log --pretty=oneline
abc123 feat: added user auth module
def456 feat: implemented login form
Git uses HEAD to point to the current snapshot. HEAD^ refers to the immediate parent commit. To move backwards:
$ git reset --hard HEAD^
This hard reset discards uncommitted work in the working tree and moves the branch pointer backward. You can also target specific SHA IDs. If you need to recover a discarded commit ID, use git reflog to view command history:
$ git reflog
abc123 HEAD@{0}: reset: moving to HEAD^
def456 HEAD@{1}: commit: added user auth module
Workspace vs. Index States
Understanding the three stages of version control is critical:
- Working Directory: Visible files on your disk.
- Index (Staging Area): Temporary storage created when adding files.
- Repository: The permanent history stored in
.git.
Unstaged changes exist only in the Working Directory. Once added via git add, they reside in the Index. Finally, git commit writes them to the Repository permanently.
Removing a tracked file requires explicit removal from Git:
$ rm utils/helper.js
$ git status
deleted: utils/helper.js
$ git rm utils/helper.js
$ git commit -m "remove deprecated helper function"
Simply deleting the file locally does not update the repository history until git rm is executed and committed.
Remote Synchronization
Connect your local repository to a remote server to enable sharing:
# Link remote server named 'origin'
$ git remote add origin https://github.com/orgname/reponame.git
# Push local changes to the remote
$ git push -u origin main
The -u flag sets the upstream tracking, simplifying future push commands. To clone an existing repository:
$ git clone https://github.com/orgname/reponame.git
Branching Strategy
Create and manage parallel histories without affecting the main line:
# List existing branches
$ git branch
# Create and switch to a new branch
$ git checkout -b feature-auth
# Merge branch into current branch
$ git merge feature-auth
To visualize the branching topology:
$ git log --graph --pretty=oneline
By default, merges often use Fast Forward mode. To force a merge commit that preserves branch history, use --no-ff:
$ git merge --no-ff -m "feat: integrate authentication service" feature-auth
Temporarily save unfinished work to switch contexts:
$ git stash
Saved working directory and index state WIP on main
Retrieve saved changes later:
$ git stash pop
Collaborative Workflows
When multiple developers modify shared files, direct pushes may fail due to divergence. The standard reconciliation process involves:
- Attempt to push your local branch.
- If rejected, fetch and pull updates from the remote to merge incoming changes.
- Resolve any content conflicts manually.
- Commit the resolved state and push again.
If local branches lack tracking information relative to the remote, establish the link:
$ git branch --set-upstream-to=origin/dev dev
Handling conflicts during a pull operation requires resolving discrepancies in the affected files before committing. This ensures the repository remains consistent across all distributed copies.