40 Git Interview Questions

Are you prepared for questions like 'How can you revert a commit that was pushed and is now public?' and similar? We've collected 40 interview questions for you to prepare for your next Git interview.

Did you know? We have over 3,000 mentors available right now!

How can you revert a commit that was pushed and is now public?

To revert a commit that was pushed and is now public, you can use the 'git revert' command. This command creates a new commit that undoes the changes made in the commit you want to revert, rather than removing the commit from the project history.

The general form of the command is git revert <commit> where <commit> is the SHA hash ID of the commit you want to revert.

Here's an example: git revert 5876f2a

After running this, Git will open up a text editor with a pre-made commit message. Once you save and exit the text editor, a new commit will be created that undoes the changes made in the specified commit.

Keep in mind that this change needs to be pushed to the remote repository to ensure that it's reflected there as well.

Using 'git revert' is the recommended method for undoing a public commit, as it doesn't alter the existing commit history. This is important to ensure that other developers working on the project don't encounter issues when they fetch the updated data.

How can you handle a Git merge conflict?

A Git merge conflict occurs when there are competing changes to the same line of code in two different branches. When you try to merge these branches, Git is unsure which changes to incorporate and gives you a conflict error.

To handle a Git merge conflict, you need to manually edit the conflicted files to decide which changes should be kept. The areas where conflicts occur will be marked with conflict markers <<<<<<, ======, and >>>>>>. The code between <<<<< HEAD and ====== represents your changes, whereas the code between ====== and >>>>>> represents the changes in the branch you're trying to merge.

Once you've decided which changes to keep, you remove the conflict markers and make sure the code is functioning as you want. Then you can add the resolved files to staging using git add.

Once all conflicts are resolved and added to staging, you can use git commit to complete the merge. Remember that during this commit, a default commit message containing information about the merge will be prefilled in the text editor. You can, of course, edit this message to suit your needs before saving and exiting the editor.

How can we undo the last commit?

There are a few ways to undo the last commit in Git, but the two main commands are git reset and git revert.

If you want to remove the last commit but keep the changes you made, you use git reset --soft HEAD~1. This command moves the HEAD to the previous commit (denoted by HEAD~1) and leaves your working directory and the staging area as they were. The changes from the undone commit will be kept as modifications in your working directory.

If you want to completely get rid of the last commit and all changes associated with it, you use git reset --hard HEAD~1.

However, if you want to "undo" the commit but keep its changes as a new commit, you'd want to use git revert HEAD. This command basically creates a new commit that undoes the last commit. This is a safe command to use, especially when you are collaborating with others, as it doesn't alter commit history.

What is Git?

Git is a free and open-source distributed version control system that's designed to handle everything from small to very large projects with speed and efficiency. It's basically a system that records changes to a file or set of files over time so that you can recall specific versions later. It allows multiple people to work together on a project concurrently, helping manage the changes made to the project. Git is widely used for its versatility in aiding source code management for development and for its ability to handle large amounts of data and distributed workflows.

What is the use of the .gitignore file?

The .gitignore file is a text file where each line contains a pattern for files/directories to ignore. It's primarily used to avoid committing unnecessary files to the repository, files that are generated from compiled source code, for instance.

Typically, this includes log files, binary files, or package/dependency folders. As an example, for a project written in Java, the .gitignore file might include the /target folder which contains compiled class files, and .log files.

Another use case might be to ignore environment-specific files. Say, a developer might have a .env.local file containing local database passwords or API keys - these should not be committed to the repository. Including them in the .gitignore file ensures they remain local.

In short, the .gitignore file helps keep the repository clean and avoids the accidental inclusion of unnecessary or sensitive files.

What is the difference between 'git checkout' and 'git checkout — '?

Both 'git checkout' and 'git checkout --' are used in Git to switch between different versions of files, but they are used in slightly different scenarios.

'git checkout [branch]' is used when you want to switch from the branch you are currently on to another branch. Say, if you are on the 'master' branch and you want to switch to the 'develop' branch, you would run 'git checkout develop'.

On the other hand, 'git checkout -- [file]' is used when you want to discard the changes made to a file in your working directory since the last commit. For instance, if you have a file named 'test.txt' and you've made some changes that you no longer want, running 'git checkout -- test.txt' will revert 'test.txt' back to the state of the last commit. The '--' is used as a separator between the command and the file names to avoid ambiguity.

In summary, 'git checkout [branch]' is used for switching branches, while 'git checkout -- [file]' is used for discarding changes in the working directory.

Can you explain what a repository in Git is?

A repository in Git, also known as a "repo", is essentially a directory for your project. Repositories hold all your project’s files and revision history, providing a structure for tracking changes, managing code, and facilitating collaboration. They can live on your local machine, or on a remote server or hosting service like GitHub. In addition to files and source code, repositories contain other important information like logs of commits, references to commit objects, and a HEAD file that points to the latest commit in the repository. A Git repository provides the foundation for version control functionality and collaborative development in Git.

What is the GIT stash operation and when would you use it?

The git stash operation allows you to temporarily save changes that you have made to your working directory but do not want to commit yet, so that you can switch branches, pull in updates, or perform other Git operations. It takes your modified tracked files and staged changes, saves them away for later use, and then reverts them, thus leaving your working directory clean.

You could use the git stash command when you are in the middle of working on something but need to switch context. An example could be if you're halfway through fixing a bug and then need to switch branches to work on an urgent task. You don't want to commit half-done work, so you can use git stash to save your changes and apply them later when you return to the task. When you're ready to go back to your previous work, you can use git stash apply to bring your changes back into your current working branch. It's a practical way to maintain a clean commit history without losing your place in your work.

What is a conflict in Git and how can it be resolved?

A conflict in Git occurs when two or more contributors make changes to the same line of the same file, or if one person edits a file and another person deletes the same file. When these conflicting changes are attempted to be merged back into the main branch, Git cannot automatically decide which changes to accept, and requires manual intervention to resolve the conflict.

Here's a simple way to handle a Git conflict:

  1. First, identify where the conflict is. Git will mark conflicts in the problematic file.

  2. Open the file and look for the conflict markers <<<<<<, ======, and >>>>>>. The code between <<<<< HEAD (your changes) and ====== is what's on the current branch, and the code between ====== and >>>>>> (the incoming changes) is what's on the branch you're merging.

  3. Manually fix the conflict by deciding which changes to keep. This might involve compromising between the two sets of changes, or it might mean keeping one and discarding the other.

  4. Once you've fixed the conflicts, you need to tell Git by staging the file with git add [file] and then commit your changes with git commit.

This will resolve the conflict and allow you to continue with the merge operation.

How does Git handle file renaming?

Git is quite intelligent when handling file renaming. It doesn't explicitly track file renaming like some other version control systems do. Instead, if Git notices that a file was deleted and another file with similar content and a different name was created, it would interpret it as a rename operation.

This approach is called 'rename detection' and Git does it automatically in a number of commands such as git diff and git log which have the '--follow' option. Git looks at the file contents and moves in relation to the other files in the commit to work out if it was a renaming operation, even if the file was also modified while it was renamed.

It's worth noting that Git also provides a rename command (i.e., git mv) to rename and effectively move a file within a repository. Although it's not necessary to use it, this command can make file renaming more explicit.

Can you explain what a commit is in Git?

A commit in Git represents a single, cohesive change or a set of changes to your code. It's a snapshot of the changes you have made to the tracked files in your project at a specific point in time. Each commit includes a unique identifier (a hash), a commit message describing the changes made, and metadata including the author's name and email, and the timestamp of the commit.

The commit process involves two steps usually: staging, where you select the changes that will be part of the next commit, and the actual commit, where Git permanently stores a snapshot of the project's current state in the repository history.

Commits provide a history of the project and its alterations, so you can see what was done when and by whom. This also allows you to rollback to previous versions if necessary.

How can a developer use 'forking' in Git?

Forking in Git is a practice predominantly used on version control platforms like GitHub or Bitbucket. A 'fork' is essentially a personal copy of someone else's project. This allows developers to freely explore and experiment with changes without affecting the original project.

Developers primarily use forking in open source projects, where they can't directly push their changes. Here are the steps of the process:

  1. First, they would 'fork' the project, which creates a copy of the repository under their own account.
  2. They can then clone this fork to their local machine using the git clone command and work on the code as needed.
  3. Then, they push the changes to their own forked repository using git push.
  4. If they want to propose their changes to the original repository, they can open a 'pull request'. The maintainers of the original repository can then review the changes and decide whether to incorporate them.

In addition to contributing to open source, forking can also be used for exploring someone else's code without affecting the original repository.

How can you instruct Git to ignore certain files?

You can use a .gitignore file in Git to specify the files or directories that you want Git to ignore and not track. The .gitignore file should be placed in the root directory of the repository and can also control the non-versioning of certain types of files across the repository or within specific directories.

The patterns in the .gitignore file are glob-like and the following wildcard characters can be used:

  • '*' matches any string of characters
  • '?' matches a single character
  • '[abc]' matches 'a', 'b', or 'c'
  • '**' in the middle of a pattern matches directories and files in all levels

Directories are indicated with a trailing '/', and to ignore every file in a directory, just list the directory's name.

Here's an example .gitignore file:


ignore all .txt files


but track test.txt, even though you're ignoring .txt files above


ignore all files in the doc/ directory


ignore file.txt in the very top level directory

/file.txt ```

Don't forget to commit the .gitignore file to the repository so that the ignore patterns can be shared with others.

What do you understand by 'git pull' and 'git push'?

'Git pull' and 'git push' are two fundamental commands used for interaction with remote repositories.

'Git pull' is a command used to fetch the latest changes from a remote repository and merge them into the local branch. Essentially, it's a combination of 'git fetch', which fetches updates from the remote repository, and 'git merge', which merges any new changes into your current branch.

On the other hand, 'git push' is the command used to upload your local repository content to a remote repository. After you make commits in your local branch and are ready to share the changes with the team on the remote repository, you would 'push' those changes so all collaborators can see them.

These two commands are central to the collaborative aspect of Git, allowing team members to stay up to-date with each other's changes and share their own.

What is rebasing in Git?

Rebasing in Git is the process of moving or combining a sequence of commits to a new base commit. It's a way to integrate changes from one branch into another.

When you rebase, you are effectively taking the changes that were committed on one branch and replaying them on another branch.

Unlike merging, which pulls the content of the feature branch into the main branch, rebasing swaps the order to make it look like the feature work happened after the work on the main. This can create a cleaner, more linear project history.

However, rebasing can also be more problematic than merging, especially if conflicts arise, because instead of resolving all conflicts in one commit, you may need to resolve conflicts in each commit separately. For this reason, it's generally recommended to use it for small changes or local cleanup, and always in a cautious manner.

How do you create a branch in Git?

Creating a branch in Git is a straightforward command-line operation. Here are the steps:

  1. First, you need to be sure you're in the branch where you want the new branch to be created from. Most of the time, this would be the main or master branch. You can switch to this branch with git checkout main.

  2. Once you're in the correct branch, you create a new branch with the command git branch [branch-name]. Replace [branch-name] with your desired name for the branch.

  3. Now, the branch has been created, but you're not "on" it yet. To switch to your new branch, you use git checkout [branch-name].

Git also allows you to create and switch to the new branch in one command using git checkout -b [branch-name].

Remember to keep branch names succinct and descriptive, as they are meant to provide context about the work being done on them.

How do you delete a branch in Git?

Deleting a branch in Git is done with the 'git branch' command, accompanied by the '-d' option for a safe delete or '-D' option for a force delete.

To safely delete a branch, which checks if the branch's changes were merged before deletion, you use git branch -d [branch-name]. If the branch's changes were not merged, Git will give you a warning and prevent you from deleting it.

If you are sure that you want to delete the branch regardless of whether or not it was merged (which means potentially discarding all changes), you can force delete it with git branch -D [branch-name].

Remember that you can't delete a branch you are currently on. You must first switch to a different branch before you can delete the one you want to remove.

Please note that these commands delete local branches. To delete a remote branch, you use git push origin --delete [branch-name].

What is a 'bare repository' in Git?

A 'bare' repository in Git refers to a repository that consists only of the .git folder and no working directory. This means it doesn't contain the actual project files, it only contains the metadata about the repository stored in the .git subdirectory.

A bare repository is generally used as a centralized sharing point. Since it has no working directory, you can't modify files or commit changes in it. It's only used to store the Git history and collaborate with other developers.

You can create a bare repository using the git init --bare command. Bare repositories are commonly used on server-side repositories that are the central collaboration point for multiple developers, such as on GitHub or GitLab, to keep the repository clean and avoid unfinished changes or unresolved conflicts.

How would you save your local modifications to a new stash and apply it later, if needed?

In Git, 'stashing' is a feature that allows you to save changes that you've made but don't want to commit yet to a stack of unfinished changes that you can reapply at any time.

  1. To save your changes to a new stash, you use the command git stash save "description of stash". Replace "description of stash" with a brief description to remember what changes are in the stash.

  2. Your working directory is now back to the state of the last commit, and you can make new commits or switch branches.

3a. If you want to reapply the changes later on, you use git stash apply. If you have multiple stashes, each one will be assigned a name like stash@{0}, stash@{1}, etc. You can specify which stash to apply like this: git stash apply stash@{1}.

3b. If you want to apply the latest stash you made, you can just use git stash apply without specifying the stash name.

Extra tip: To see a list of your stashes, you can use the git stash list command.

Remember, 'apply' leaves the stash in your stack for future use. If you want to apply a stash and remove it from the stack, use 'git stash pop' instead.

Can you describe how Git branching works?

Git branching is a feature that allows developers to create independent lines of development within a project. It's like creating a unique work environment where changes made on one branch do not affect other branches.

When you create a branch in Git, you are essentially creating a pointer to a specific commit in the repository. The default main line of development is usually called the 'main' or 'master' branch. When you create a new branch, say for developing a new feature, it becomes a separate copy of the codebase at the point of branching.

You can work on this branch without affecting the main branch. When the work on the branch is complete and tested, it can be merged back into the main branch. If the changes are no longer needed, the branch can be deleted without impacting the main branch.

This model of branching is what allows multiple team members to work concurrently on a project, each on their own branch, without interfering with each other's work.

What are the basic commands for creating a new repository in Git?

Creating a new repository in Git involves just a few basic steps and commands.

Firstly, navigate to the directory where you want to create your new repository. Use the cd command to change directories to wherever you want the new repo to be located.

Next, you'll use the git init command to initialize a new Git repository. It creates a new .git subdirectory in your current directory. This .git directory contains all the necessary metadata for your new repo.

Here is an example of these steps:

cd /path/to/directory git init

After initializing your new repository, you're ready to start adding files and making commits. To add files, you can use the git add command, and to make a commit, you use git commit -m "Commit message".

Remember, until you make a commit, no information will be stored in the repository.

Please explain the requirements for security in Git.

When considering security in Git, a few key things come to mind.

Firstly, access control. You need to ensure only authorized individuals have access to your Git repositories. This can be achieved through key-based SSH access or user management features available in Git services like GitHub, GitLab, and Bitbucket.

Secondly, data integrity is a core feature of Git. Every object in a Git repository has a unique SHA-1 hash which verifies the integrity of the object. If a file were altered, the hash would change, indicating a discrepancy.

Thirdly, to enhance security, sensitive data like passwords or API keys should never be committed to a Git repository. If these have been committed accidentally, they should be purged from the history.

Then, you should consider signing your commits and tags using GPG or S/MIME. This provides an extra layer of security by ensuring that the changes and tags are coming from a trusted source.

Lastly, always keep your Git client up to date. This ensures that you’re protected from any vulnerabilities found in previous versions.

In conclusion, while Git itself does a good job maintaining the integrity and consistency of your code, the way Git is used in collaboration environments requires you to consider and enforce additional security measures.

What is cherry-pick in Git?

Cherry-picking in Git is a way to apply changes from specific commits to your current working branch. If you find a commit in one branch that would be useful on another, you can use the 'cherry-pick' command to apply that commit directly to your current branch without merging all the changes from the source branch.

The command would be git cherry-pick [commit-hash], where [commit-hash] would be the ID of the commit you want to cherry-pick. You can get this commit hash from the git log.

It's a handy tool when you want to include useful changes that were made elsewhere without integrating an entire branch's worth of changes, allowing for more granular control over your Git history. Keep in mind, though, the cherry-picked commit is a completely new and different commit, even though the change set is the same. It has a new hash and new parent commit, and it may lead to duplicate changes when merging branches in the future.

How would you connect to a remote repository in Git?

Connecting to a remote repository in Git is a straightforward operation generally performed with the git remote command. The 'remote' in Git is a common repository that all team members use to exchange their changes.

To connect to a remote repository, you would use the git remote add command followed by the shortname you'll use to refer to that remote and the URL of the remote repository.

Here is an example: git remote add origin https://github.com/user/repo.git

In this command, 'origin' is commonly used as the default shortname to refer to the original remote repository. However, you can name it however you want.

After adding a remote, you can use git remote -v to verify that the new remote exists beneath the specified shortname.

To interact with this remote repository, you would then use git fetch, git pull, and git push commands with the given shortname (e.g., git push origin main).

How do you set up a Git repository to run code sanity-checking tools right before making commits, and reject the commit if the test fails?

You can achieve this functionality in Git using a mechanism called hooks. These are scripts that Git executes before or after events like commit, push, and receive. To run sanity checks or tests before a commit, you'd set up a pre-commit hook.

A pre-commit hook is a script stored in the 'hooks' directory within the Git directory (.git/hooks). This script is triggered every time you execute the git commit command.

In this script you'd define the tests or checks that you want to run. For example, if your code sanity-checking tool is a script named 'run-tests.sh', your pre-commit hook might contain:



./run-tests.sh ```

If this script exits with a non-zero exit status, the commit will be aborted. Meaning, if your 'run-tests.sh' command fails (suggesting a test failure or unsuccessful sanity check), the commit won't be made.

Remember to make this script executable using the command chmod +x .git/hooks/pre-commit.

In this way, Git ensures that only code that passes the sanity checks is committed to the repository.

Can you explain the difference between Git and SVN?

Git and SVN (Subversion) are both version control systems but they have quite a few differences in structure and functionality.

Firstly, Git is a distributed version control system, which means that every developer's working copy of the code is also a repository that can contain the full history of all changes. This allows for operations like committing and branching to be done locally without a network connection.

Conversely, SVN is a centralized version control system. This means there is a single, central repository, and when users make changes, they're committing them directly to that central repository. Requires network connection for most operations.

Secondly, branching in Git is seamless and an integral part of the workflow whereas in SVN, branches are implemented as a separate directory in the system.

Lastly, due to its distributed nature, Git allows multiple developers to work on the same code simultaneously without overriding each other's changes. SVN, being a centralized system, can cause more conflicts when merging.

In general, while both have their uses and advantages, Git is more powerful and flexible, and accommodates various workflows better than SVN. It's preferred for its robustness, local access to the full development history, and superior branching and merging capabilities.

What is the function of 'git rm'?

The 'git rm' command is used to remove files from the working directory as well as the Git staging area (index). Essentially, it tells Git that you want to include file deletions in your next commit.

If you have a file in your repository that you no longer need, you can use 'git rm [file-name]' to remove the file. This removal is then staged and ready to be committed, meaning that at the next commit, the file will not only be removed from your working directory but also from the repository.

Remember that 'git rm' can only remove files that are tracked by Git. In other words, the files you're removing must be identical to their state at the latest commit.

Keep in mind 'git rm --cached' if you wish to keep the file in your local file system but have Git stop tracking it. This is often used to remove files mistakenly added to a Git repository when they should have been ignored.

What are some ways to find a commit that introduced a bug in Git?

Git offers powerful tools to help track down the commit that introduced a bug. Here are a couple of ways:

  1. Git log: You can use the git log command to view the commit history. Using various flags, you can narrow your search and change the display format. This can be useful to manually review recent commits if you roughly know when the bug was introduced.

  2. Git blame: The git blame command shows line-by-line details for a file including which commit last modified each line. This can be particularly useful if the bug relates to a specific part of your code as it helps pinpoint which commits could have introduced the issue.

  3. Git bisect: The most powerful tool for this purpose is git bisect, which uses a binary search algorithm to help you find which commit introduced the bug. You give it a known good commit, a known bad commit, and then it will checkout a commit in the middle of that range. You test if the bug is in that commit, tell Git whether it's good or bad, and then it chooses the next commit for you to test. You repeat this process until Git has pinpointed the exact commit that introduced the bug. This is especially useful in large-scale projects with extensive commit histories.

How do you switch from one branch to another?

Switching from one branch to another in Git is quite straightforward and can be done using the git checkout command. For instance, if you have a branch named 'development' and you want to switch to it from your current branch, you would type git checkout development in your terminal.

It's important to note that before switching branches, you should have a clean working state, meaning all changes should be either committed or stashed, because uncommitted changes will be carried over to the branch you’re checking out. If those changes conflict with the branch you’re checking out, Git will not allow the checkout operation.

What is a 'detached HEAD' in Git?

A 'detached HEAD' state in Git refers to the situation in which the HEAD pointer is not pointing to any branch, but instead directly to a commit. In other words, you're not working on any branch.

You might enter a detached HEAD state when you check out a specific commit rather than a branch, using a command like git checkout [commit-hash].

While in a detached HEAD state, you can browse through the project’s history, but any changes you make won’t belong to any branch and will be lost if you don’t create a new branch to save them.

If you make changes that you want to keep while in the detached HEAD state, you should create a new branch using git checkout -b [new-branch-name]. If you checkout to another commit or branch without doing this, those changes will be lost, as no branch reference will be keeping them active.

What do you do when your repository becomes too heavy with unused objects?

When a Git repository becomes too heavy with unused objects, this can be cleaned up using the 'git gc' command, which stands for 'garbage collection'.

Git automatically performs garbage collection when certain thresholds are met. However, you can manually run garbage collection with git gc command. This command cleans up unnecessary files and optimizes your local repository.

The 'git gc' command will collect all loose objects (unused and old data) into pack files to reduce the disk space and increase performance.

For a more aggressive cleanup, you can use the git gc --aggressive command, which can provide additional space savings, at the cost of taking longer to run.

Before running the 'gc' command, you might want to run 'git prune' to remove objects that are no longer pointed to by anything in your repository, followed by 'git reflog' to remove information about old branches and commits. This ensures that 'gc' has the most up-to-date view of your repository's data.

How can you compare two different commits in Git?

If you want to compare two different commits in Git, you can use the 'git diff' command followed by the hashes of the two commits you want to compare. For instance, if you have commits with the hashes commit1 and commit2, you'd type:

git diff commit1 commit2

This will show the differences between the two commits in terms of lines added and removed. '+' signs indicate additions, while '-' signs indicate deletions.

You can find the hashes of existing commits by using the 'git log' command, which shows a list of previous commits along with their SHA-1 checksums.

If you wish to see a detailed breakdown of which files have changed and how, you can use the '--stat' option, like so:

git diff --stat commit1 commit2

That'll show you the number of insertions and deletions in each file between the two commits.

Can you describe 'Git clean'?

'Git clean' is a command that's used to remove untracked files from your working directory. Essentially, it cleans your working directory by removing files that are not under version control.

For example, you might have just built your project and have lots of build files interspersed with your source code. If you wanted to remove all those build files, you could use 'git clean'.

By default 'git clean' will not remove directories or ignored files, and it will ask for confirmation before actually deleting anything.

If you want to remove directories as well, you can use the -d argument, like so: git clean -d.

If you want Git to remove ignored files too, use the -x argument: git clean -x.

To skip the confirmation, use the -f (force), like so: git clean -fd to remove untracked files and directories.

Remember that 'git clean' is one of the few Git commands that can permanently delete files, so make sure you really want to delete these untracked files before you run it.

How does the workflow in Git differ from other version control systems?

One of the key differences in workflow between Git and other version control systems is that Git is a distributed version control system, meaning every developer's copy of the code is also a repository that can contain the full history of all changes.

In centralized systems like Subversion (SVN) or Perforce, there's a single, central repository. Users checkout certain files or directories onto their local machine, and the .svn directories (in the case of SVN), for example, do not contain a complete repository but rather enough to redo or undo your changes before you commit back to the central repository. These systems require a connection to the central repository for most operations.

With Git, nearly all operations are local – you generally only interact with the remote repository to publish or share your work. This leads to better performance (since you don’t need network access to view history), and your work can be done offline. Merging and branching are much more straightforward operations in Git because of this design philosophy.

In addition, Git stores data as a series of snapshots (as opposed to the delta-based approach employed by many other systems), which contributes to its speed, data integrity, and support for nonlinear workflows.

Git also encourages workflows that branch and merge often, even multiple times a day. This is largely due to how inexpensive and automatic the merge operation is. Alternately, workflows in other version control systems often involve locking files and committing to one mainline branch.

What is the 'Git reset' command, and how does it differ from the 'Git revert' command?

The 'git reset' command in Git is used to reset your current HEAD to a specified state. You can use it to undo changes in the staging area and, with the --hard option, in the working directory as well. It can effectively be used to undo commits, but only in a local repository.

Here's a usage example: if you wanted to undo the last commit, you could use git reset --hard HEAD~1.

However, using 'git reset' can be dangerous in a public repository because it alters the commit history.

On the other hand, the 'git revert' command undoes a commit by creating a new commit that undoes the changes made in the previous commit. It reverses the effect of an earlier commit and preserves the project history.

For instance: git revert HEAD will introduce a new commit that undoes the last commit.

So while both 'reset' and 'revert' can be used to undo changes, 'reset' does so by moving branch pointers around (making it appear as if the commit never happened), whereas 'revert' does so by applying a new commit that undoes the changes. 'revert' is generally safer and is preferred if the commit you want to undo has already been pushed to a public repository.

What does 'git bisect' do?

'git bisect' is a powerful tool in Git that allows you to perform a binary search through your commit history in order to find the specific commit that introduced a bug or issue. This can be very helpful if the bug was introduced a while ago and there are many commits to go through.

The process starts by defining a 'good' commit (a commit where the issue did not exist) and a 'bad' commit (a commit where the issue is present). 'git bisect' then checks out a commit midway between the 'good' and 'bad' commits, where you can then test if the issue exists or not. If the issue is there, it's a 'bad' commit. If it's not, it's a 'good' commit.

After this, 'git bisect' selects a new commit midway between the newly defined 'good' and 'bad' commits. Over a few iterations, 'git bisect' narrows down the search range until it pinpoints the specific commit that introduced the bug.

Once the culprit commit is found, you can use 'git bisect reset' to end the bisecting process and go back to where you started. If used effectively, 'git bisect' can save a lot of time in debugging by quickly finding the source commit of an issue.

What is a submodule and when should it be used?

A submodule is like a Git repository inside another Git repository. It allows you to keep another Git repository in a subdirectory of your repository, enabling you to track changes in both repositories separately.

Submodules are useful when you want to include an external library or project into your own project while keeping the commit history of both projects separate. Instead of copying the entire code of the external project into your own, you just create a submodule which references the exact commit of the external project you want to include in your own project.

To create a submodule, you use the command git submodule add [repository] [path]. This will clone the repository to the specified path, and it will be tracked as a submodule. You then commit the .gitmodules file created in your repository, which stores the mapping between the project URL and the local subdirectory.

When someone clones your repository, they will need to use the --recursive option with the git clone command, or use git submodule init and git submodule update after cloning to fetch all the data from the submodules.

So submodules allow you to keep parts of your project loosely coupled and separately versioned, which can be useful in many situations, especially when working with external libraries or components.

How do you go to a particular version of a file?

To checkout a particular version of a file in Git, you need to know the hash of the commit that has the version of the file you want. This can be found using the 'git log' command. Once you have the hash, you use the 'git checkout' command, followed by the commit hash and the name of the file. For example:

git checkout commit_hash file_name

This will update the specified file to its state at the specified commit.

Please note that this change is now an uncommitted change in your working directory. If you want to keep this version of the file, you need to commit it. If you want to go back to the version of the file on your original branch, you can use git checkout -- file_name.

This clears local changes and resets the file to the version on the current branch. So, be cautious when using these commands, especially if you have local changes that you don't want to lose.

Can you explain the concept of Git hooks?

Sure! Git hooks are custom scripts that are triggered in response to certain events in Git, such as a commit, push, or branch creation. These scripts allow you to automate tasks, enforce rules, or alter the default behavior of Git.

For example, you can create a pre-commit hook that runs tests or checks code style, preventing the commit if the tests fail or the style checks don't pass.

All Git hooks reside in the .git/hooks directory of a Git project. When you initialize a new repository, Git populates the hooks directory with a set of example scripts, all of which are disabled by default (they're named with a '.sample' extension).

To create a new hook, you would create a script without a file extension (e.g., "pre-commit" instead of "pre-commit.sample") in the hooks directory. This script should be executable and should exit with a status of 0 if successful, or a non-zero status if unsuccessful.

Git hooks are not version-controlled, which means they are not shared with the repository when it is cloned or fetched. This is because hooks can execute any script or program on your system and can be a potential security risk if misused.

How would you handle the situation if you deleted a branch accidentally?

If you've accidentally deleted a branch in Git, you can often recover it because Git keeps a log of all the updates to the repository's ref, which includes operations like creating, deleting, and updating branches.

Firstly, you can use the git reflog command to check the history of head pointers. This command will give you a list of previous commits, along with an index HEAD@{index}. Look for the entry just before the delete operation.

Once you find the commit hash before the deletion, you can bring your branch back with the git checkout -b <branchname> <commit-hash> to recreate the branch with the last known commit.

Remember to replace <branchname> with the name of the branch you deleted, and <commit-hash> with the commit hash you found from git reflog.

Remember though, this method is reliable only for a certain period, typically 30 days, after which Git's garbage collection may remove the commit objects. Therefore, it is important to recover the lost branch as quickly as possible.

Get specialized training for your next Git interview

There is no better source of knowledge and motivation than having a personal mentor. Support your interview preparation with a mentor who has been there and done that. Our mentors are top professionals from the best companies in the world.

Hello! My name is Massoud(pronounced Masuud) and I'm originally from Nashville TN. Aside from marketing I also enjoy meditating, yoga, traveling, and trying different foods. I began my marketing career in 2019 through freelancing, and contract work. My favorite marketing channel is paid search where I have increased ROI in …

$180 / month
2 x Calls

Myke Metzger was born in Long Island, New York (1989) and is an author, professional speaker, and entrepreneur. With over 250,000 followers his content has racked up over 20 million views. He has helped hundreds of other verified influencers and creators improve their branding, marketing, and content creation. He is …

$150 / month

Only 1 Spot Left

With over 12 years of experience in web development, Jeff is a senior frontend engineer. Jeff is proficient in React, Redux, Material UI, Apollo GraphQL, HTML5, Node.js, Next.js, Remix, React-Query, React-router as well as other technologies and tools that keep him updated and adaptable in the fast-growing frontend community. Jeff …

$160 / month
2 x Calls

Akram RIAHI is an Site Reliability Engineer (SRE) with an interest in all things Cloud Native. He is passionate about kubernetes resilience and chaos engineering at scale and is Litmus Chaos leader. A curator of quality tech content, he is the author of several blog posts and organizer of the …

$240 / month
2 x Calls

Only 1 Spot Left

As a global brand director, I have led some of the most iconic brands in the world, such as Dove, Rexona (Sure/Degree), and Axe (Lynx) at Unilever. I genuinely enjoy helping others grow their skillset, achieve both their professional and personal goals through mentoring and coaching. I have a strong …

$400 / month
4 x Calls

Only 2 Spots Left

Hiii 👋 Sourav is a lead software engineer, leads a team of software developers responsible for developing and building applications. Sourav is a full-stack developer specializing in building high-scalability, high-resilience distributed systems. Sourav will help you prepare for coding interviews, System Design for FAANG and other top product companies, and …

$120 / month
2 x Calls

Browse all Git mentors

Still not convinced?
Don’t just take our word for it

We’ve already delivered 1-on-1 mentorship to thousands of students, professionals, managers and executives. Even better, they’ve left an average rating of 4.9 out of 5 for our mentors.

Find a Git mentor
  • "Naz is an amazing person and a wonderful mentor. She is supportive and knowledgeable with extensive practical experience. Having been a manager at Netflix, she also knows a ton about working with teams at scale. Highly recommended."

  • "Brandon has been supporting me with a software engineering job hunt and has provided amazing value with his industry knowledge, tips unique to my situation and support as I prepared for my interviews and applications."

  • "Sandrina helped me improve as an engineer. Looking back, I took a huge step, beyond my expectations."