80 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 80 interview questions for you to prepare for your next Git interview.

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's the best way to prepare for a Git interview?

Seeking out a mentor or other expert in your field is a great way to prepare for a Git interview. They can provide you with valuable insights and advice on how to best present yourself during the interview. Additionally, joining a session or Git workshop can help you gain the skills and knowledge you need to succeed.

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

*.txt

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

!test.txt

ignore all files in the doc/ directory

doc/

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:

```

!/bin/sh

./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.

How do you clone an existing Git repository?

To clone an existing Git repository, you use the git clone command followed by the URL of the repository you want to clone. For example, you would run something like git clone https://github.com/username/repo.git. This command will create a directory with the name of the repository and set it up with all the files and commit history from the source repository. If you want to clone into a directory with a different name, you can add that name at the end of the command like git clone https://github.com/username/repo.git mydir.

What is Git and why is it used?

Git is a distributed version control system primarily used for tracking changes in source code during software development. It's designed to handle everything from small to very large projects with speed and efficiency. By creating snapshots of the project at various points in time, Git allows multiple developers to collaborate, track their progress, manage branches, and merge changes seamlessly. This makes it invaluable for maintaining the integrity and history of codebases through various iterations.

What is the purpose of the `.gitignore` file?

The .gitignore file is used to tell Git which files or directories to ignore in a project. This is particularly useful for excluding temporary files, build outputs, dependency directories, and other files that shouldn’t be version controlled. By specifying file patterns in the .gitignore file, you can keep your repository clean and focused only on the files and directories relevant to your project's source code.

How do you switch between branches in Git?

You can switch branches using the git checkout command followed by the branch name, like git checkout branch-name. In newer versions of Git, you can also use git switch branch-name, which is more intuitive. If the branch doesn't exist yet and you want to create and switch to it, you could do git checkout -b new-branch-name or git switch -c new-branch-name.

What is the difference between `git merge` and `git rebase`?

git merge combines two branches by creating a new commit that integrates changes from both branches. It preserves the history of both branches, so you can see all commits from the branches involved. On the other hand, git rebase takes the commits from a branch and re-applies them on top of another branch. This rewrites the commit history, creating a linear sequence of commits, which can make the project's history cleaner but may require a bit more care to avoid issues, especially with shared branches.

What command is used to commit changes in Git?

To commit changes in Git, you'd use the git commit command. Typically, you'll follow it up with the -m flag to add a message describing what that commit includes, like git commit -m "Fixed bug in user authentication". You need to stage changes first using git add <files> before committing them.

How do you push changes to a remote repository?

To push changes to a remote repository, first make sure you've staged and committed your changes locally. After that, you'll use the git push command. Most of the time, it looks something like git push origin main, where origin is the remote name and main is the branch you want to push to. If it’s your first time pushing to a specific branch, you might need to set the upstream using -u, like git push -u origin main. Once set, future pushes can be as simple as just git push.

Can you explain the difference between `git add` and `git commit`?

git add and git commit are two fundamental operations in Git, but they serve different purposes. git add is used to stage changes. This means you're selecting the specific changes you want to include in your next commit. It moves changes from the working directory to the staging area, preparing them to be committed.

On the other hand, git commit actually records the staged changes in the repository’s history. When you commit, you're taking a snapshot of the current state of the staged files. This snapshot is stored in the Git history, allowing you to go back to it later if needed. So, in essence, you use git add to gather changes and git commit to save them as part of your project's history.

What does the `git status` command do?

The git status command shows the current state of the working directory and the staging area. It lets you see which changes have been staged, which haven't, and which files are not being tracked by Git. It’s a great way to get a quick overview of what’s going on in your repository before committing.

How do you rename a branch in Git?

Renaming a branch in Git is pretty straightforward. If you want to rename the branch you are currently on, you would use the command git branch -m new-branch-name. If you need to rename a different branch, just include the old branch name: git branch -m old-branch-name new-branch-name.

Remember that if you have already pushed the old branch to a remote repository, you will also need to delete the old branch from the remote and push the new one. You can do this with git push origin --delete old-branch-name and then git push origin new-branch-name. Don't forget to set the upstream for the new branch using git push --set-upstream origin new-branch-name.

Can you explain the differences between Git and other version control systems?

Git is a distributed version control system, which means every developer has a full copy of the repository including its history, allowing for more flexible collaborative workflows. This is in contrast to centralized systems like Subversion (SVN), where there's typically a single central repository and developers check out a working copy.

Git also excels at branching and merging, making these processes much faster and more intuitive compared to some other systems. This capability encourages small, frequent commits and more experimental workflows since merging is relatively painless. Systems like Mercurial or Perforce might have some of these features, but Git's community support and ubiquity give it a unique edge.

How do you initialize a new Git repository?

To initialize a new Git repository, you simply navigate to the directory you want to make a repository and run the command git init. This will create a new .git subdirectory there, which includes all of the metadata and object database for your new repository. After that, you can start adding files with git add and commit them with git commit.

How can you view the commit history in Git?

To view the commit history in Git, you use the git log command. By default, it shows a list of commits in reverse chronological order, with details like commit hash, author, date, and the commit message. If you want a more compact view, you can add options like --oneline to show each commit on a single line. Other useful options include --graph to visualize the branch structure, or --stat to see the file changes made in each commit.

Can you explain the concept of branching in Git?

Branching in Git is like creating a parallel universe of your codebase where you can work on features or fixes without affecting the main project. It's essentially a pointer to a specific commit within the timeline of your project's history. When you create a branch, you can diverge from the main line of development and continue to work independently. Once you're satisfied with the changes on your branch, you can merge it back into the main branch, like integrating that parallel universe back into the original one. This allows multiple developers to work on different features simultaneously without stepping on each other’s toes.

How do you create a new branch in Git?

To create a new branch in Git, you use the git branch command followed by the name you want for the new branch. For example, git branch new-feature creates a branch called new-feature. To switch to that branch, you use git checkout new-feature. Alternatively, you can create and switch to a new branch in one step using git checkout -b new-feature. This makes it easy to start working on a new feature or fix without affecting the main codebase.

What is a pull request?

A pull request is a way for developers to notify team members that they have completed a feature or fix and would like to merge their changes into the main codebase. It's essentially a request to "pull" in your changes. This process allows for code review, discussion, and any necessary revisions before the changes get integrated. It’s especially useful in collaborative environments to maintain code quality and consistency.

How do you stage changes for commit in Git?

To stage changes in Git, you use the git add command followed by the file name or path you want to stage. This moves the changes from your working directory into the staging area. If you want to stage all the changed files at once, you can use git add .. This will stage any new, modified, or deleted files. Essentially, staging is like preparing a snapshot of your changes before you actually commit them to your repository.

How do you fetch changes from a remote repository?

To fetch changes from a remote repository, you generally use the git fetch command followed by the name of the remote, commonly origin. It retrieves any updates from the remote branches but doesn't automatically merge those changes into your working directory or your current branch. So you'd run something like git fetch origin. After fetching, you can inspect the changes and decide how to incorporate them, like with git merge or git rebase commands.

What is a fork in Git and how do you use it?

A fork in Git is essentially a personal copy of someone else's project. It allows you to freely experiment with changes without affecting the original project. Forking is typically done on platforms like GitHub, where you can click the "Fork" button on a repository to create your own copy under your account.

Once you've forked a repository, you can clone it to your local machine, make changes, and push updates to your forked version. If you want to contribute back to the original project, you can submit a pull request from your fork, suggesting that the original project incorporate your changes. This workflow is really useful in collaborative environments, especially in open source software development.

Can you explain the difference between a soft reset and a hard reset?

A soft reset in Git primarily alters the commit history without modifying the working directory or the staging area. Essentially, it moves the HEAD pointer to a specified commit, so you can change the commit history, but your actual changes in files remain untouched.

On the other hand, a hard reset goes a few steps further—it not only moves the HEAD pointer to a specified commit but also updates the staging area and the working directory to match that commit. This means any changes made after that specific commit will be discarded. It's a way to fully revert to a previous state, including all tracked files in your project.

What is a detached HEAD state in Git?

A detached HEAD state in Git happens when you've checked out a commit instead of a branch. Imagine your HEAD is like a pointer to where you currently are in your repository. Normally, it's pointing to the latest commit in a branch. But in a detached HEAD state, it's pointing directly to a specific commit, not following any branch. This means that if you make any new commits in this state, they won't be associated with any branch and could be hard to find unless you create a new branch from there. It's useful for looking back at previous states without affecting your current branch.

How do you delete a branch in Git?

To delete a branch in Git, you would use the git branch -d command for local branches. For example, git branch -d branch_name deletes a branch named branch_name. If the branch hasn't been fully merged, you might need to use -D (uppercase D) instead, like git branch -D branch_name, which forces the deletion.

If you want to delete a remote branch, you use git push origin --delete branch_name. This will remove the branch from your remote repository like GitHub or GitLab.

How do you resolve merge conflicts in Git?

When you encounter a merge conflict in Git, you’ll usually see conflict markers in the files where Git couldn’t automatically merge changes. These markers, like <<<<<<<, =======, and >>>>>>>, denote the conflicting sections. To resolve them, you need to manually edit the file to choose or combine the changes that should remain.

After fixing the conflicts, you can mark the file as resolved by running git add <filename> and then commit the merge using git commit. If you want to see the list of files with conflicts, you can use git status. Tools like git mergetool can also help simplify the process by providing a visual interface for resolving conflicts.

What is the difference between `git fetch` and `git pull`?

git fetch downloads the latest changes from the remote repository but doesn't apply them to your local branches. It updates your remote-tracking branches, so you can inspect the changes before deciding to merge them into your local branch.

On the other hand, git pull is like a combination of git fetch followed by git merge. It fetches the changes from the remote repository and directly merges them into your current branch in one step. This can be convenient but occasionally causes merge conflicts that you'll need to resolve.

How do you create a tagged release in Git?

To create a tagged release in Git, you first make sure you're on the branch you want to tag, usually the main or master branch. Then, you use the git tag command followed by a version identifier, like git tag v1.0.0. If you want to include a message with the tag, you can add the -a flag and use -m to add your message, like so: git tag -a v1.0.0 -m "Initial release". Finally, don't forget to push the tags to the remote repository using git push origin --tags. This way, your tag will be available to everyone collaborating on the project.

Can you explain the concept of a Git stash?

A Git stash is essentially a way to save your uncommitted changes temporarily without committing them. Imagine you're in the middle of working on something, and you need to switch branches either to work on something else or to pull in updates. Rather than committing your half-done work or discarding it, you can stash it. This saves your changes in a neat stack for you to apply later. Just run git stash to stash your changes and git stash pop to reapply them when you're ready. It's super handy for keeping your workflow smooth and your working directory clean.

How do you apply a stash in Git?

To apply a stash, you can use the git stash apply command. This takes the most recent stash and applies it on top of your current working directory. If you want to apply an older stash, you can specify it with git stash apply stash@{index}, where index is the stash number from the list you get with git stash list. After applying, the stash is still kept in the stash list until you drop it with git stash drop or clear all stashes with git stash clear.

What is the purpose of the `git reset` command?

git reset is a powerful command used to undo changes in your working directory and staging area, and optionally in your commit history. It essentially moves the current branch pointer to a specified commit. Depending on the options you use, it can affect your working directory and staging area differently. With --soft, it only moves the commit history, leaving the working directory and index untouched. With --mixed, it moves the commit history and updates the index but not the working directory. And --hard resets everything, including your working directory and index, to match the specified commit.

How do you revert a commit in Git?

Reverting a commit in Git can be done with the git revert command. This command generates a new commit that undoes the changes from a specific previous commit. You just need to specify which commit you want to revert by its hash. For example, you would run git revert <commit-hash>, and Git will create a new commit that reverses the changes introduced by the specified commit while keeping the project's history intact.

If you're only looking to revert the most recent commit, you can simply run git revert HEAD. This method is especially useful because it preserves the commit history and avoids potential conflicts that might arise from other methods, like resetting. If you made a mistake in the revert command itself, you can always revert the revert commit the same way.

If working with a team, after reverting the commit, you should push the changes to the remote repository with git push, ensuring everyone is on the same page.

How do you handle conflicts that arise during a Git rebase?

When conflicts arise during a Git rebase, the process pauses at the conflicting commit, and you're given a chance to resolve the conflicts. First, I use git status to see which files are in conflict and then manually resolve the conflicts by editing the files. After resolving the conflicts, I add the resolved files to the staging area using git add, and then I continue the rebase with git rebase --continue. If I need to abort the rebase for any reason, I can use git rebase --abort. Always make sure to thoroughly test the resolved changes to avoid any integration bugs later.

How do you amend a commit in Git?

If you need to change the most recent commit in Git, you can use git commit --amend. This is useful if you forgot to include some changes or need to edit the commit message. First, make the necessary changes in your working directory and stage them using git add. Then, run git commit --amend. This will open your default text editor where you can update the commit message if needed. After saving the changes, the previous commit will be amended with the new changes.

How do you squash multiple commits into one?

To squash multiple commits into one, you can use an interactive rebase. Let's say you want to squash the last three commits. You'd run git rebase -i HEAD~3. This opens up an editor where you see a list of the last three commits. You can change the word "pick" to "squash" (or just "s") for the commits you want to merge into the previous one. Save and close the editor, then another editor window will open allowing you to change the commit message of the squashed commits. Save and close it, and you're done! The history will now show one combined commit instead of the three individual ones.

What is the purpose of the `.gitattributes` file?

The .gitattributes file is used to define attributes for different paths in your repository. It allows you to customize settings on a per-path basis, such as managing line endings, specifying merge strategies, or setting up filters for specific file types. For example, you can configure .gitattributes to ensure that text files have standardized line endings across different operating systems or to mark certain files as binary so that Git treats them accordingly.

What is a Git submodule and how is it used?

A Git submodule allows you to include and manage a separate Git repository within your main project's repository. It's especially useful when your project depends on external libraries or components that you want to keep versioned and updated independently.

To use a submodule, you'd typically run git submodule add <repository> to add the external repository as a submodule. This command will add a reference to the submodule in your project and create an entry in a .gitmodules file. Once added, you can clone your main repository with the --recurse-submodules option to ensure that all submodules are cloned as well. Managing submodule updates involves pulling changes in the submodule directory and committing the updated reference in your main project.

What is the purpose of the `git config` command?

The git config command is used to configure settings and preferences for Git. This can include setting up your username and email for commits, defining how Git should handle line endings, or specifying aliases for commands to make your workflow more efficient. It allows for customization at three levels: system-wide, user-wide, and per-repository, which helps in managing different setups based on your needs.

Can you explain the use of `git cherry-pick`?

git cherry-pick is a command that allows you to apply the changes introduced by an existing commit to your current branch. It's really useful when you want to bring in a specific change from another branch without merging the entire branch. For example, if there's a bug fix on a feature branch that you need on your main branch, you can cherry-pick that commit. Just find the commit hash you want to pull in and use git cherry-pick <commit-hash>.

What is the `git bisect` command used for?

git bisect is a really handy command for tracking down which specific commit introduced a bug or issue. It automates a binary search through your commit history, allowing you to identify the problematic commit more quickly. You start by marking a known good commit and a known bad commit, and then Git will guide you through checking commits in between until the bad one is found. It's a lifesaver when you're dealing with a large number of commits and can't figure out where things went wrong.

How do you secure your Git repository and manage permissions?

Securing your Git repository and managing permissions involves a few key practices. First, always use SSH for authentication rather than HTTP, since SSH keys provide a more secure connection method. For hosting platforms like GitHub, GitLab, or Bitbucket, make sure to set up two-factor authentication (2FA) to add an extra layer of security to your account.

For permissions, you should rely on the access control methods provided by your hosting service. These often allow you to set repository visibility (public or private) and manage who can read, write, or administer the repository. Additionally, it's a good idea to use branch protection rules to enforce certain workflows, such as requiring pull request reviews or passing status checks before merging code into a protected branch. This not only enhances security but also maintains code quality.

How do you compare differences between two commits in Git?

You can compare differences between two commits using the git diff command. The basic syntax is git diff commit1 commit2, where commit1 and commit2 are the SHA-1 hashes of the two commits you want to compare. This will show you the changes that would change commit1 into commit2. If you don’t supply a second commit, git diff will compare commit1 with the working directory. If you want a more visual and easier-to-navigate comparison, you might use git difftool with the same arguments, which can open the diff in tools like Meld or Beyond Compare.

What strategies or policies do you follow for managing branches in a large project?

For managing branches in a large project, I typically follow a branching strategy like Git Flow or Trunk-Based Development, depending on the project's requirements and team structure. Git Flow involves using branches for features, releases, and hotfixes, which helps in organizing work and maintaining stability in the main branch. It's particularly useful for projects with regular releases.

On the other hand, Trunk-Based Development focuses on keeping the main branch as the primary working branch, with short-lived feature branches that are frequently merged back into the trunk. This approach minimizes merge conflicts and keeps the deployment cycle fast and continuous.

Regardless of the strategy, enforcing code reviews through pull requests is crucial to maintain code quality. Additionally, integrating automated testing in the CI/CD pipeline ensures that any changes made in branches don't break the build, maintaining overall project health.

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.

Only 1 Spot Left

Need help with data science and machine learning skills? I can guide you to the next level. Together, we'll create a personalized plan based on your unique goals and needs. Whether you want to build a strong portfolio of projects, improve your programming skills, or advance your career to the …

$390 / month
  Chat
2 x Calls
Tasks

Only 2 Spots Left

Are you a junior developer eager to accelerate your career in web development? Do you seek expert guidance on learning the most relevant and up-to-date content, building real-world projects, and excelling in job interviews? Together, let's unlock your full potential by overcoming challenges, addressing your queries, and charting a roadmap …

$210 / month
  Chat
3 x Calls
Tasks

Only 5 Spots Left

As a top mentor with a proven playbook, I’ve helped countless professionals worldwide pivot careers, secure promotions, and rediscover their direction, all backed by 5/5 feedback from over 20 mentees. I'm committed to providing the tools needed to find that next job and providing ways of accountability. Some of our …

$300 / month
  Chat
Regular Calls

Only 1 Spot Left

I am a Senior Front End Software Engineer with over 10 years of experience at various tech companies, currently based in Toronto, Canada. I am currently working at Square and was previously at Coinbase, Taplytics. I have previously mentored at Lighthouse Labs: Canada's Leading Coding Bootcamp. I have professional, hands-on …

$600 / month
  Chat
4 x Calls
Tasks


Eugene is a faith-centric technologist, a serial entrepreneur, angel investor, advisor and mentor. He is founder of REACTIVE LIONS INC. where he is implementing his vision of faith-driven entrepreneurship in the tech world. He is currently running a team of over 40 talented engineers across the US. Eugene is the …

$120 / month
  Chat
Tasks

Only 1 Spot Left

Hello, I'm Abhishek Koserwal, a Principal Software Engineer at Red Hat and a dedicated mentor ready to guide you on your career journey. Whether you're just starting as a software engineer or trying to identify your best career path, I'm here to help you succeed. Designing your career: Together, we'll …

$120 / month
  Chat
1 x Call

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."