Mastering Git: Essential Concepts and Commands for Developers

What is Git?

  • git is an essential tool for software development

  • It manages and maintains the versions of codes to enable developers track the changes in their codebase.

  • it creates a common platform to collaborate with others and it maintains a history of the modifications.

  • It provides few awesome features like branching, merging & reverting the changes.

I have written the same article on my LinkedIn page as well - https://www.linkedin.com/pulse/start-git-partho-das-4ruwc/

Git Initialization and Files Created

When the git is initialized using git init, Git creates a hidden directory called .git in the root of the project.

The .git directory contains these files.

  • HEAD: It is a reference to the latest commit in the current branch.

  • config: It is the configuration settings of the repository.

  • description: Provides a brief description of the repository.

  • hooks/: Directory containing client-side and server-side scripts that Git can run at different points in the workflow.

  • info/: Directory containing the exclude file for ignored patterns specific to the repository.

  • objects/: Directory storing all objects (blobs, trees, commits, tags) in the repository.

  • refs/: Directory containing pointers to commit objects (branches, tags).

Git Tracking and Workflow

Git tracks changes to files of a software development project through a series of stages:

  1. Working Directory: The working directory is where the developers writes/modifies their file. These changes are not yet tracked by Git.

    1. run the command git status and this will show which file is tracked by git and which is untracked.

    2. Staging Area (Index): The staging area is a place where the changes are prepered before committing them.

      • Changes to the staging area are added using git add . for adding all files.

      • for adding any specific file, we can use git add file_name

  2. Local Repository: The local repository is where committed changes are stored. Commits are actually the snapshots of project history.

  3. Remote Repository: The remote repository, such as GitHub or BitBucket, is a version of the repository hosted on a remote server. It serves as a central source of truth for collaboration.

Git Commands and Workflow

image source - Google images

  • Adding Changes: git add <file> moves changes from the working directory to the staging area.

  • Committing Changes: git commit -m "message" moves changes from the staging area to the local repository.

  • Pushing Changes: git push moves commits from the local repository to the remote repository.

  • Fetching Changes: git fetch retrieves updates from the remote repository without merging them.

  • Pulling Changes: git pull fetches and merges changes from the remote repository into the local repository.

Resetting and Reverting

  • Reset: git reset changes the state of the repository by moving the HEAD pointer. It can be used with different options:

    • git reset --soft <commit>: Moves HEAD to the specified commit, keeping changes in the staging area.

    • git reset --mixed <commit>: Moves HEAD to the specified commit, removing changes from the staging area but keeping them in the working directory.

    • git reset --hard <commit>: Moves HEAD to the specified commit, removing changes from both the staging area and working directory.

    • git push -f this push needs to be forced to make the remote repo head also adjusted same as the local repo head. [This will result the changes in the commit number on the remote repo]

  • Revert: git revert <commit> creates a new commit that undoes the changes of the specified commit, preserving the project history.

Monitoring and Inspecting with Git

  • git log: Displays the commit history.

  • git blame <file>: Shows who made changes to each line of a file.

  • git show <commit>: Displays detailed information about a specific commit.

  • HEAD: Refers to the current branch reference. By default, it points to the latest commit in the branch. Using commands like git reset --hard HEAD~1 can reset the branch to a previous commit.

Connecting to a Remote Repository

  • Adding a Remote: git remote add origin <url> connects your local repository to a remote repository.

  • git remote --v this will give the information about the remote repo for both push and fetch

  • Cloning a Repository: git clone <url> creates a copy of a remote repository locally.

  • Pushing to a Remote: git push -u origin <branch> pushes changes to the specified branch in the remote repository and sets the upstream.

  • Pull Requests: A feature on platforms like GitHub that allows developers to review and merge code changes from different branches or forks.

Git Branching

Why Do We Need Separate Branches?

  1. Isolation of Work:

    • Isolation: Each branch allows developers to work on separate features, bug fixes, or experiments without affecting the main codebase.

    • Stability: The main branch remains stable, while development occurs in other branches.

  2. Collaboration:

    • Collaboration: Multiple developers can work on different features or fixes simultaneously without stepping on each other's toes.

    • Code Review: Using branches makes it easier to review and approve changes before merging them into the main codebase.

  3. Continuous Integration:

    • Testing: Branches allow for continuous integration and testing of new code before it is merged into the main branch.

    • Deployment: Feature branches can be deployed to test environments for validation before merging.

  4. Feature Development:

    • Feature Branches: Separate branches for each feature ensure that incomplete or experimental features do not disrupt the main codebase.

Creating and Managing Branches

Create a Branch Locally: git branch feature-xyz

Switch to the Branch: git checkout feature-xyz

Or, git checkout -b feature-xyz

Push the Branch to Remote: git push -u origin feature-xyz // Here -u upstream

Updating Branches

Pull Latest Changes: git pull origin feature-xyz

Sync Local Branch with Remote: Fetch changes from the remote repository and merge them to local branch:
git fetch origin && git merge origin/feature-xyz

Brach naming best practices:

wip - for any work that is in progress

feat - for any specific feature

bug - bugs

Create a branch for cart feature

git checkout -b feat/cart [git branch feat/cart && git checkout feat/cart]

Branch Tagging

Tags are used to mark specific points in the commit history, usually for releases.

Create a Tag: git tag v1.0.0

Push Tags to Remote:git push origin v1.0.0

List Tags:git tag

Merging Branches

Merge a Branch into Another: Switch to the branch that needs to be merged into (e.g., main) and merge the other branch (e.g., feature-xyz):
- switching to the branch where the other branch needs to be merged git checkout main

Now, execute this command for the brnach that needs to be merged with the main branch git merge feature-xyz

Resolve Conflicts: If there are conflicts during the merge, only option is to resolve them manually by talking with the other contributors, stage the resolved files, and commit: git add <resolved-file> && git commit

Stashing Changes :

We have done some work on our working directory, but we happen to pull the remote repo to keep it updated, we can stash our local developed work temporary and once the pull of code is completed from the remote, we can reapply the stashed code back to our working area.

  • git stash

  • and then do git pull and get the remote code available on the working local

  • now we can apply our stashed code on that by git stash apply

Stash Changes: git stash

List Stashes: git stash list

Apply Stash: git stash apply

Apply and Drop Stash: git stash pop

Drop a Specific Stash: git stash drop <stash@{index}>

Lets try to get the Workflow

  1. Create a New Feature Branch: git checkout -b feat/feature-login

  2. Work on the Feature and Commit Changes:

    • git add .

    • git commit -m "Add login feature"

  3. Push the Branch to Remote: git push -u origin feat/feature-login [ -u is upstream]

  4. Update the Branch with the Latest Main Branch Changes:

    • git checkout main

    • git pull origin main

    • git checkout feat/feature-login

    • git merge main

  5. Resolve Any Conflicts, if Necessary:

    • git add resolved-file

    • git commit

  6. Push the Updated Feature Branch:

    • git push origin feat/feature-login
  7. Create a Pull Request on GitHub:

    • Go to the GitHub repository.

    • Navigate to the Pull requests tab.

    • Click New pull request.

    • Select feat/feature-login as the branch to merge into main branch

    • Create the pull request and request a review.

  8. Merge the Pull Request After Review:

    • Once approved, merge the pull request on GitHub.
  9. Update Local Main Branch:

    • git checkout main

    • git pull origin main