Advanced Git techniques enable developers and DevOps engineers to manage complex workflows, maintain a clean and readable project history, and integrate changes selectively. These techniques are particularly important in collaborative projects, CI/CD pipelines, and large-scale applications where multiple developers work simultaneously on different features, bug fixes, or release branches. Mastering advanced Git ensures that code changes are traceable, conflicts are minimized, and the repository remains organized. It also allows teams to maintain stable production branches while still developing new features efficiently.
Rebasing is an advanced Git operation that moves or reapplies commits from one branch onto another branch, creating a linear commit history. Unlike merging, which preserves all branch structures and creates a merge commit, rebasing rewrites the commit history to make it appear as though the feature branch was developed directly on top of the target branch.
Rebasing is particularly useful for keeping feature branches updated with the latest production or main branch changes. It reduces unnecessary merge commits, simplifies logs, and makes code review easier. A clean linear history improves traceability and is preferred in DevOps pipelines for automated builds and deployments.
Example: If the main branch has commits M1 → M2 → M3 and a feature branch has F1 → F2, rebasing the feature branch onto main results in M1 → M2 → M3 → F1 → F2.
Command for rebasing:
git checkout feature-branch
git rebase main
During rebasing, conflicts may occur if the same code is modified in both branches. Git pauses the rebase and highlights conflicting files. Developers must resolve conflicts manually, stage the resolved files using git add <file>, and continue the rebase with git rebase --continue.
Rebasing ensures that feature branches are always aligned with the main branch, reducing integration issues during automated deployments. It also makes the project history linear and easier to navigate, which is critical in DevOps pipelines where frequent merges can complicate builds and releases.
Cherry-picking is a Git operation that allows developers to apply a specific commit from one branch onto another branch without merging the entire branch. This is valuable for selectively including critical bug fixes or features into production branches while excluding unrelated changes.
Cherry-picking provides granular control over code integration, ensuring that only desired commits affect the target branch. This is particularly useful in DevOps environments where urgent fixes need to be deployed without waiting for the full feature branch to be stable or completed.
Example: If a feature branch contains a bug fix commit F2, you can apply it to the main branch using cherry-pick, without merging other feature changes.
Command for cherry-picking:
git checkout main
git cherry-pick <commit-hash>
Cherry-picking helps maintain branch stability by allowing urgent updates without disturbing ongoing development. It is widely used in DevOps pipelines to patch production systems, update release branches, or quickly deliver hotfixes.
3) Resolving Merge Conflicts
Merge conflicts occur when Git cannot automatically combine changes from two branches due to overlapping edits in the same lines of a file or related files. Conflicts are common in collaborative projects, especially when multiple developers modify the same sections of code.
When conflicts occur, Git marks the conflicting sections in the file and shows changes from each branch. Developers must manually review, edit, and decide which changes to keep.
After resolving conflicts, the modified files are staged using git add <file>, and the merge or rebase process is completed using git commit or git rebase --continue.
Efficient conflict resolution is crucial in DevOps to ensure CI/CD pipelines remain stable, automated tests pass, and deployments do not break production environments. Proper conflict resolution prevents regressions and ensures that the merged code accurately reflects the intended changes from all contributors.
Best practices include communicating with team members, reviewing changes carefully, and testing merged code before pushing to remote repositories. Using rebasing and cherry-picking strategically also reduces the frequency of conflicts.
Interactive Rebase (git rebase -i) – Allows editing, reordering, squashing, or deleting commits interactively, giving complete control over commit history. This is useful for cleaning up messy commit sequences before merging to main or release branches.
Stashing (git stash) – Temporarily saves uncommitted changes to allow switching branches without losing work. DevOps engineers often use stashing when needing to quickly switch context during deployments or bug fixes.
Reflog (git reflog) – Tracks changes to the repository’s HEAD, allowing recovery from accidental resets or deletions. This provides a safety net for DevOps teams managing critical production branches.
Tags (git tag) – Mark specific commits as release points, enabling easy rollbacks, versioning, and tracking of deployed code in CI/CD pipelines.
Submodules (git submodule) – Allows including external repositories within a repository. Useful in large-scale projects or microservices architectures, where different teams maintain separate codebases.
Advanced Git workflows like Git Flow or GitHub Flow integrate these operations to streamline collaboration, enforce release policies, and automate deployments in DevOps pipelines.
Advanced Git techniques such as rebasing, cherry-picking, conflict resolution, interactive rebases, stashing, and tagging are essential for professional developers and DevOps engineers. They provide flexibility, control, and organization in managing code across multiple branches, teams, and environments. Mastering these techniques ensures smooth collaboration, clean commit histories, stable pipelines, and reliable production deployments.
GitHub is one of the most widely used platforms for version control, collaboration, and DevOps integration. It provides a centralized environment for managing source code, automating workflows, and improving team productivity. Beyond being a simple code repository, GitHub enhances software quality, security, and workflow efficiency. Its integration with CI/CD pipelines, project management tools, and automation platforms makes it indispensable for modern software development and DevOps practices.
.jpg)
GitHub is built on Git, a distributed version control system. Every developer has a full copy of the repository locally, allowing them to work offline and track changes independently. This setup ensures that all changes are logged, reversible, and traceable. In DevOps, this distributed nature reduces dependency on a central server, prevents data loss, and allows teams to maintain multiple versions of code safely across different environments.
GitHub allows multiple developers to work on the same project simultaneously using branching, pull requests, and forks. Branching isolates feature development from the main codebase, while pull requests enable team members to review changes before integration. This collaboration improves communication, prevents conflicts, and ensures that high-quality code is merged. For DevOps, such teamwork is crucial to integrate development, testing, and operations workflows efficiently.
GitHub integrates seamlessly with continuous integration and continuous deployment (CI/CD) tools like Jenkins, GitHub Actions, Travis CI, and CircleCI. This enables automated building, testing, and deployment of applications directly from the repository. Automation reduces manual intervention, speeds up delivery, ensures reliable deployments, and allows early detection of bugs, which aligns perfectly with DevOps principles of rapid and iterative software delivery.
GitHub’s pull request and review system allows team members to analyze, comment, and approve code changes before merging into the main branch. This peer review process ensures that only quality, tested, and standard-compliant code is deployed. It helps maintain high code quality, reduce defects, and enforce best practices, which is critical in DevOps pipelines where automated deployments rely on stable and error-free code.
GitHub serves as a secure, centralized repository for all project files, including code, configuration files, and documentation. It ensures that work is safely backed up and accessible to authorized team members from anywhere. This centralization prevents data loss, supports distributed teams, and enables efficient project collaboration, which is especially important for geographically distributed DevOps teams.
GitHub offers project boards, milestones, labels, and issue tracking to manage tasks, feature requests, and bugs. Teams can plan sprints, assign tasks, and monitor progress within the repository. In DevOps, this organized approach improves transparency, accountability, and workflow efficiency, ensuring timely delivery of features and fixes.
GitHub hosts millions of open-source projects and libraries. Teams can leverage existing tools, frameworks, and best practices, reducing development time and effort. Open-source collaboration fosters innovation, encourages learning from the global community, and allows teams to contribute improvements, benefiting both their projects and the wider developer ecosystem.
Git is a distributed version control system designed to track changes in source code and project files. Unlike traditional centralized version control systems, Git allows every developer to maintain a complete local copy of the repository, including its full history, branches, and commits. This ensures that developers can work independently while still contributing to a shared project. Git is essential for modern software development because it provides a structured workflow for managing project versions, coordinating team contributions, maintaining code integrity, and enabling collaborative development across different locations. It allows for experimentation with new features, seamless merging of changes, and precise rollback capabilities in case of errors. By mastering Git commands, developers can manage repositories efficiently, control the staging and committing of changes, create and merge branches safely, interact with remote repositories, and maintain a robust project history.
The git init command initializes a new Git repository in an existing directory or project folder. When executed, it creates a hidden .git folder that contains all the metadata, object data, references, commit history, and configuration files required for version control. This folder acts as the backbone of the repository, allowing Git to track every file modification, manage branches, stage changes, and perform merges. By initializing a repository, developers convert a regular project directory into a fully version-controlled project, capable of supporting collaborative development and detailed change tracking. This is the very first step in establishing a Git-managed workflow and forms the foundation for all future operations on the repository.
Example:
git init my-project
This creates a new Git repository inside the my-project folder, enabling tracking of all future changes.
The git clone command is used to create a local copy of an existing remote repository. Unlike git init, which starts a new repository, git clone copies the complete project history, branches, tags, and configuration from a remote source. This is critical for collaboration because it ensures that every contributor starts with an identical working copy of the project. The command also sets up a connection to the remote repository, making it possible to push local changes back to the remote and pull updates from the team. Cloning supports distributed workflows by allowing developers to work offline, experiment locally, and synchronize changes efficiently without affecting the central repository until they choose to push their work.
Example:
git clone https://github.com/user/repo.git
The git config command allows developers to customize Git behavior and define essential user information. Global configuration settings apply to all repositories on the system, while local settings apply only to a specific repository. Key configurations include the user’s name and email, which are recorded in commits to ensure accountability and traceability. Other configuration options include default editors, merge strategies, color settings, and line-ending preferences. Proper configuration ensures that collaboration is smooth, commits are correctly attributed, and team members can review and understand project history clearly. Without proper configuration, commits may appear anonymous or inconsistent, which can create confusion in collaborative environments.
Example:
git config --global user.name "Mayank Mehra"
git config --global user.email "mayank@example.com"
The git add command moves changes from the working directory to the staging area. The staging area acts as a preparation zone where Git collects all the modifications that are intended to be included in the next commit. This allows developers to selectively include or exclude changes, giving fine-grained control over what is committed. By staging files, developers can review, organize, and confirm changes before they become a permanent part of the project history. The staging mechanism ensures that commits remain structured, meaningful, and easy to understand, which is crucial for collaborative development, code reviews, and rollback operations.
Example:
git add file1.txt
git add .
The git commit command records the staged changes into the repository along with a descriptive commit message. Each commit is assigned a unique hash identifier that allows developers to trace, compare, and revert changes at any point in the project’s history. Commits form the chronological timeline of the project, documenting how the code evolves over time. Proper commit practices, including clear messages, make it easier to understand the purpose of changes, track progress, and manage collaboration. Commits also allow branching, merging, and rollback operations to be carried out reliably because they capture the precise state of the project at a specific moment.
Example:
git commit -m "Added user login functionality"
The git branch command allows developers to create, list, or delete branches. Branches are separate lines of development that enable work on new features, bug fixes, or experiments without affecting the main codebase. Branching ensures that multiple developers can work concurrently on different aspects of the project, reducing conflicts and enabling isolated testing and development. Each branch has its own history and can later be merged into other branches once development is complete. This workflow supports parallel development and maintains project stability.
Example:
git branch feature-login
The git checkout command is used to switch between branches or restore specific files from previous commits. This allows developers to navigate between different lines of development, test features independently, and revert files to a known good state if necessary. By switching branches, developers can isolate experimental work, test bug fixes, and work on multiple tasks simultaneously without interfering with the main project history.
Example:
git checkout feature-login
The git merge command integrates changes from one branch into another, typically merging feature branches into the main branch. During merging, Git automatically combines changes but may require manual conflict resolution if the same lines of code were modified in both branches. Merging ensures that new features, improvements, or fixes are integrated safely while preserving the project’s history. It is a fundamental operation for collaborative development and maintaining a clean, unified codebase.
Example:
git checkout main
git merge feature-login
The git remote command manages connections to remote repositories. It allows developers to fetch updates, push changes, and synchronize their local repositories with a central server. Managing remotes is crucial for collaboration, as it defines the sources of truth for the project and enables coordinated development across teams.
Example:
git remote add origin https://github.com/user/repo.git
The git push command uploads local commits to a remote repository. Pushing changes keeps the remote repository up to date and allows team members to access the latest updates. This operation is essential for sharing work, collaborating on features, and deploying applications.
Example:
git push origin main
The git pull command fetches changes from a remote repository and merges them into the local branch. It ensures that the local repository remains synchronized with the latest updates from other contributors. git pull simplifies collaboration by integrating remote work into a local environment seamlessly.
Example:
git pull origin main
The git reset command moves the HEAD pointer to a previous commit, allowing developers to undo changes while optionally keeping modifications in the working directory. It provides a flexible way to reorganize commits, discard unwanted changes, or restructure project history.
Example:
git reset --soft HEAD~1
The git revert command creates a new commit that undoes the effects of a previous commit without altering project history. This method is safer than git reset in collaborative environments because it preserves the integrity of the commit timeline while effectively reversing changes.
Example:
git revert <commit_hash>
The git status command displays the current state of the working directory and staging area, including modified, staged, and untracked files. It helps developers track what changes are ready to be committed and which files require attention.
Example:
git status
The git diff command shows differences between working files, staging area, and commits. It allows developers to review modifications, analyze changes before committing, and ensure that updates are accurate. This is critical for maintaining code quality and avoiding unintended changes.
Example:
git diff
git stash temporarily saves changes in the working directory that are not yet ready to commit, allowing developers to switch branches or work on urgent tasks without committing incomplete work. Stashing is useful when you need to pause work on one feature and attend to another task, ensuring that uncommitted changes are preserved safely. The stashed changes can later be reapplied to the working directory.
Example:
git stash
git stash apply
git stash list
This sequence saves the current changes, reapplies the latest stash, and lists all stashed changes.
git tag creates references to specific points in the repository history, usually used for marking release versions, milestones, or important commits. Tags are immutable pointers that make it easy to identify, checkout, or deploy specific versions of the code. Tags can be lightweight or annotated, with annotated tags storing additional metadata such as author, date, and description.
Example:
git tag v1.0
git tag -a v1.1 -m "Added login feature"
git push origin v1.1
git cherry-pick allows developers to apply a specific commit from one branch to another without merging the entire branch. This is useful when you need a bug fix, feature, or update from a different line of development but do not want to merge all the other changes from that branch. Cherry-picking helps maintain flexibility and fine-grained control over changes applied across branches.
Example:
git checkout main
git cherry-pick <commit_hash>
git rebase re-applies commits from one branch onto another base, allowing developers to maintain a linear and clean project history. Rebase rewrites commit history, which can reduce merge conflicts and make the timeline easier to read. However, rebasing modifies commit hashes, so it should be used carefully, especially on shared branches. Rebase is commonly used to integrate upstream changes or clean up feature branches before merging into the main branch.
Example:
git checkout feature-login
git rebase main
git bisect is a powerful debugging tool that uses binary search to find the commit that introduced a bug or regression. It automatically checks out commits between a known good state and a known bad state, allowing developers to test and pinpoint the exact commit causing the problem efficiently. This tool is extremely valuable for large projects with long histories.
Example:
git bisect start
git bisect bad
git bisect good <commit_hash>
git log displays the commit history of the repository. It provides detailed information about each commit, including the author, date, commit hash, and message. Developers can use various options to filter, format, and search the commit history. git log helps track progress, audit changes, and identify contributors or commits related to specific features or fixes.
Example:
git log
git log --oneline
git log --graph --decorate --all
git reflog shows a record of all moves of the HEAD pointer in the repository, including commits, checkouts, resets, and rebases. This is extremely useful for recovering lost commits, abandoned branches, or accidentally deleted changes. git reflog acts as a safety net, providing a complete timeline of repository actions.
Example:
git reflog
git checkout HEAD@{3}
git clean removes untracked files and directories from the working directory. This helps keep the repository clean by discarding temporary files, build artifacts, or files ignored by .gitignore. It is a powerful tool but should be used with caution since the deleted files cannot be recovered through Git.
Example:
git clean -f
git clean -fd
Basic commands used in Git Hub
git init → This command initializes a new Git repository in your project folder. When you run git init, Git creates a hidden .git directory inside your project. This directory contains all the metadata required to track your project’s changes, including commit history, configuration, branches, and objects. Without this initialization, Git cannot track changes or manage versions for your project. Initializing a repository is always the first step when starting a new project with Git.
Example:
mkdir MyProject
cd MyProject
git init
This will create a .git folder inside MyProject, marking it as a Git repository. After initialization, you can start adding files, making commits, and tracking your project history.
Use case: Ideal for starting a brand-new project locally from scratch.
git clone <repo_url> → This command creates a local copy of an existing remote repository on your machine. It downloads the entire repository, including all commit history, branches, tags, and configuration, allowing you to work on the project offline. Cloning is typically used when contributing to an existing project or starting development based on a remote repository.
Example:
git clone https://github.com/username/MyProject.git
This creates a folder named MyProject with the contents of the remote repository. You can make changes locally and push them back to the remote repository when ready.
Use case: Useful when collaborating on open-source projects, team projects, or when starting from a template repository.
git status → Displays the current state of the repository. It shows which files have been modified, which are staged for commit, and which are untracked. This command is essential for understanding what is happening in your repository before committing changes.
Example:
git status
Sample output:
Changes not staged for commit:
modified: file1.txt
Untracked files:
file2.txt
This output tells you which files have changes that are not yet staged for commit and which files are new and not tracked by Git.
Use case: Before committing, always check git status to avoid accidentally missing files or committing unwanted changes.
git log → Shows the commit history of the repository in chronological order. It displays each commit’s unique ID (SHA), author, date, and commit message. This command is useful to review past changes, track the evolution of the project, and identify specific commits for debugging or reverting changes.
Example:
git log
Sample output:
commit 3a2f1b4
Author: Mayank Mehra
Date: Thu Nov 21 10:00 2025
Message: Added initial project files
Use case: Helps developers understand the project’s history, track who made what changes, and find specific points in the code’s development timeline.
The command git add <file> is used to stage a specific file for the next commit. Staging is the process of selecting which changes in your working directory you want to include in a commit. This allows you to commit logically grouped changes instead of committing all changes at once. For example, if you have modified three files but only want to commit changes to file1.txt, you would run:
git add file1.txt
This stages only file1.txt for the next commit, leaving other modified files unstaged. The staging area, also called the index, acts as a buffer between your working directory and the repository. It allows you to review and organize changes before committing them. Advanced staging options such as git add -p <file> enable you to stage changes line by line, giving even more control over what goes into a commit.
The command git add . stages all changes in the current directory and its subdirectories, including new files, modified files, and deleted files. For instance, if you have created file2.txt, modified file3.txt, and deleted file4.txt, running:
git add .
will stage all these changes at once. This command is convenient when you want to prepare every change for a commit but should be used carefully in large projects to avoid committing unrelated or temporary files. To stage changes selectively within a folder, you can run git add folder_name/, which stages all changes in that folder while leaving other files untouched.
After staging, git commit -m "message" is used to create a commit containing all staged changes along with a descriptive message. Each commit acts as a snapshot of the repository at that moment, storing metadata such as author, timestamp, and a unique commit ID. For example:
git commit -m "Added login feature"
This commits the staged files with the message “Added login feature.” Clear commit messages are crucial for team collaboration and future reference, allowing developers to understand the purpose of each commit without inspecting the code.
The command git commit -a -m "message" combines staging and committing for all modified tracked files in a single step. For example, if you have modified file3.txt and file4.txt which are already tracked, running:
git commit -a -m "Fixed login bug"
automatically stages and commits all changes in tracked files. It does not include new untracked files, so new files must still be added using git add. This command is useful for quickly saving changes to existing files without running git add first.
The command git branch lists all branches in the repository and highlights the current active branch. Branching allows you to work on multiple versions of a project simultaneously without affecting the main codebase. For example, running:
git branch
might display:
* main
feature-login
Here, the asterisk * indicates the current branch (main). Branches act as pointers to commits, isolating different lines of development so you can experiment, add features, or fix bugs without interfering with the main project.
To create a new branch, git branch <branch_name> is used. For instance:
git branch feature-login
This creates a new branch called feature-login starting from the current commit. The branch is independent of main and allows you to develop a feature without affecting the stable code in the main branch. Branches are lightweight and can be created or deleted freely, making them ideal for managing multiple tasks or experiments simultaneously.
Switching between branches is done using git checkout <branch_name>. For example:
git checkout feature-login
This updates your working directory to match the feature-login branch. Any changes you make now will only affect this branch, leaving other branches untouched. You can return to the main branch at any time by running git checkout main. This allows developers to work on multiple features in parallel without mixing changes.
After completing work on a branch, git merge <branch_name> is used to integrate its changes into the current branch. For example, after finishing work on feature-login, you can switch to main and merge it using:
git checkout main
git merge feature-login
This incorporates all changes from feature-login into main. Git attempts to merge changes automatically, but if both branches modified the same lines of code, a merge conflict occurs. Conflicts must be resolved manually before the merge can be completed. After resolving conflicts and committing, the main branch includes all changes from the merged branch. Branching and merging help maintain a clean workflow, allowing developers to safely isolate features, fix bugs, and integrate updates without disrupting the main project.
A remote repository is a version of your project that is hosted on a server, such as GitHub, GitLab, or Bitbucket, which allows multiple developers to collaborate on the same codebase. The command git remote -v is used to display the URLs of all remote repositories connected to your local repository, along with the type of access you have (fetch or push). This command is very important because it helps you verify where your code is being synchronized and ensures that you are pushing and pulling from the correct remote location. For example, when you run:
git remote -v
you may see the following output:
origin https://github.com/username/MyProject.git (fetch)
origin https://github.com/username/MyProject.git (push)
This output shows that your local repository is linked to a remote repository named origin. The term origin is just a default shortcut name used for the main remote repository. The (fetch) URL is used when downloading changes from the remote server to your local machine, while the (push) URL is used when uploading your changes back to the remote server.
The command git push origin <branch_name> is used to send your local commits to a specific branch of the remote repository. This command plays a crucial role in collaboration, as it makes your changes visible and accessible to other developers working on the same project. When you type:
git push origin main
Git takes all the commits that exist on your local main branch but are not yet present on the remote main branch and uploads them to the remote repository. This ensures that your progress is safely stored on the server and can be pulled by your teammates.
The command git pull is used to update your local branch with the latest changes from the remote repository. It is a combination of two operations: git fetch (which downloads the changes) and git merge (which applies those changes to your current branch). When you run:
git pull origin main
Git first fetches the latest commits from the remote main branch and then merges them into your local main branch. This helps you stay synchronized with the current version of the project and reduces the chances of conflicts when working in a team environment. Regularly using git pull is considered a good practice in collaborative development.
In Git, undoing changes allows developers to fix mistakes, revert unwanted modifications, or recover a clean state of the project. The command git restore <file> is used to discard changes made to a file after the last commit. It basically resets the file back to its previously committed version. This is useful when you have made incorrect changes in a file and want to completely remove them. For example, when you run:
git restore file1.txt
Git replaces the modified version of file1.txt in your working directory with the version from the last commit, effectively deleting all uncommitted changes in that file.
The command git reset <file> is mainly used to remove a file from the staging area without deleting its changes. This is helpful if you have accidentally staged a file and want to edit it again before committing. For example:
git add file1.txt
git reset file1.txt
After running these commands, file1.txt will no longer be staged for commit, but all the modifications will still be present in your working directory. This gives you the freedom to make further improvements before finalizing the commit.
The command git reset --hard is a powerful command that resets your entire working directory and staging area to match the last commit. It removes all uncommitted changes permanently, including changes in all files. When you use:
git reset --hard
your project will return to the exact state of the last committed version, and any progress that was not committed will be lost forever. Because of its destructive nature, this command should be used very carefully, especially in collaborative or production environments.
Finally, the command git revert <commit_id> is used when you want to undo the effects of a particular commit without changing the project's commit history. Instead of deleting or modifying past commits, it creates a new commit that applies the opposite changes of the selected commit. This is very safe for shared repositories because it does not rewrite history. For example:
git revert 3a2f1b4
This command creates a new commit that cancels out the changes introduced by commit 3a2f1b4, while keeping all other commits intact. This makes it very useful for undoing errors in published or shared projects where rewriting history can cause problems for other developers.
We have a sales campaign on our promoted courses and products. You can purchase 1 products at a discounted price up to 15% discount.