Frequently asked questions around Git and Version Control.
Git Interview Questions - The essential list, including answers
It doesn't matter on which side of the table you're sitting: good preparation is essential for an interview on Git and version control! Here's our compilation of the most important interview questions about Git, including extensive answers.
The Git Cheat Sheet
No need to remember all those commands and parameters: get our popular "Git Cheat Sheet" - for free!
Git is a so-called "distributed" version control system. What's the difference to a "centralized" one?
Subversion is an example for a centralized version control system: all team members work towards a single central repository, placed on a remote server. A "checkout" from this central repository will place a "working copy" on the user's machine. This is a snapshot from a certain version of the project on his disk.
In Git, a distributed version control system, things work a little differently. Instead of a "checkout", a Git user will "clone" a repository from a remote server. In return, they receive a full-fledged repository, not just a working copy. The user then has their own repository on their local machine - including all of the project's history.
You can do everything on your local machine: commit, inspect history, restore older revisions, etc. Only if you want to share your work with the world will you have to connect to a remote server.
What is "bare repository" in Git?
Remote repositories in Git should be set up as "bare" repositories. Technically, a remote repository doesn't differ from a local one: it contains branches, commits, and tags just like a local repository.
However, a local repository has a working copy associated with it: a directory where some version of your project's files is checked out for you to work with.
A remote repository doesn't have such a working directory: it only consists of the bare ".git" repository folder.
What is the difference between "fetch" and "pull"?
git fetch really only downloads new data from a remote repository - but it doesn't integrate any of this new data into your working files. Fetch is great for getting a fresh view on all the things that happened in a remote repository.
git pull, in contrast, not only downloads new data; it also directly integrates it into your current working copy files. You can think of pull as a combination of fetch and merge (or, alternatively, rebase).
What is a conflict in Git?
In Git, a conflict can occur in a couple of different situations: most commonly while performing a "merge" (but possibly also when rebasing or pulling).
In most cases, Git will figure out how to integrate new changes on its own. However, there's a handful of situations where the user might have to step in and tell Git what to do.
Most notably, this is when the same lines in the same file were changed - or when one person decided to delete the file while the other person decided to modify it. In any of these cases, Git simply cannot know what is correct. Git will then mark the file as having a conflict. The user will have to solve these conflicts before they can continue their work.
Solving Conflicts in Tower
In case you are using the Tower Git client, its visual Conflict Wizard will help you solve merge conflicts more easily:
What is a "detached HEAD" in Git? Why is it considered a "dangerous" state?
Almost always when you check out a revision in your repository, you do this by mentioning a branch's name: you tell Git to make this branch your current HEAD branch. However, instead of checking out a branch, you can also choose to check out a specific commit or tag.
By doing this, you have put your local repository in a "Detached HEAD" state: the HEAD pointer is not on a branch, but on a specific revision.
If you create additional commits in this state, they will not be associated with any branch (since no branch is currently checked out). In such a scenario, it's very easy to lose new commits.
What is the "Stash" in Git? In what situations can it be helpful?
The Stash can be described as a "clipboard" for uncommitted local changes. Putting your local changes on the Stash will result in a clean working copy, i.e. you have no more local changes.
Such a "clean working copy" state is an important prerequisite for many actions in Git: e.g. before switching branches, pulling from a remote, or merging changes, you should always make sure to have a clean working copy without any local changes.
Changes that were stored on the Stash can be restored later in your working copy, at any time. You can create as many Stashes as you want; you're not limited to storing only a single set of changes.
How can you restore a previous version of your project?
The git reset command is perfect for this task: you can provide the SHA-1 hash of the commit you want to return to and thereby restore the project to that revision's state.
You committed a file and only later noticed that it actually should have been "ignored". How can you solve this?
Git only ignores "untracked" files (these are files that haven't yet been committed to the repository). If a file was accidentally committed to the repository and shall then be ignored, you have to first untrack it; this can be done, for example, by moving it out of the repository temporarily so Git considers it "deleted". After confirming this "deletion" in a new commit, you can then move the file back and add it to the project's .gitignore list.
You accidentally committed on the "master" branch instead of "feature/login". Describe the process of correcting this mistake.
First, you should check out the "feature/login" branch. There, copy the desired commit over using the git cherry-pick command. Then, check out "master" again and use git reset --hard HEAD~1 to undo the (on this branch) unwanted commit.
Why is it discouraged to us "git push --force"? What are some of the potential downsides?
Using git push with the --force option forcefully overwrites the history on the remote with your own local commit history. Two main problems can occur:
a) Your colleagues might have based their work on the old commit history. By force pushing, you have changed this history, meaning their history is not in line with the new one anymore.
b) If your colleagues have pushed their own work in the meantime (since you last fetched from the remote), a force push will overwrite (and thereby delete) their commits.
How can you undo a commit that has already been pushed to a shared branch on a remote repository?
First of all, using git push --force would not be a good solution in most cases. The reason for this is that force push has the potential to overwrite other's work or at least change their commit history in an unexpected way.
A better, unobtrusive approach would be to use git revert, because this will not rewrite / manipulate old commit history. Instead, a new commit will be created that corrects the effects of the unwanted one(s).
You have accidentally deleted a branch. Is there any way to recover it and bring it back?
Using the git reflog command, you are able to inspect all of the recent HEAD pointer movements in this repository. If the deletion hasn't been too long ago, you should be able to find the last commit on this branch. Using that commit's SHA-1 hash, you are then able to recreate the branch.
Use CMD+Z to Undo Deleting a Branch in Tower
In case you are using the Tower Git client, you can undo most actions simply by hitting CMD+Z. Here's how to restore a deleted branch:
What does it mean to "rewrite commit history"? Give some examples of when this can happen in Git.
Commit history is "rewritten" whenever existing commits are manipulated after the fact. The most important effect of this is that the manipulated commits will receive new SHA-1 hashes, making them completely new commit objects from Git's perspective. This is especially dangerous if others on a team have already based their work on this old commit history; if it's manipulated after the fact, this will cause problems.
Commit history is "rewritten", for example, during a rebase, interactive rebase, or when amending the very last commit.
Is it possible to edit an old commit's message, although newer commits have already been created?
If the commit in question had been the very last commit, an easy solution would have been to use the --amend flag of git commit. However, since other commits have been created afterwards, amending is not an option.
In such a case, Git's "interactive rebase" tool can be used to manipulate old commits - including their commit messages.
What is a Rebase in Git?
Just like a merge, rebase is a way of integrating commits from another branch into the current HEAD branch. In contrast to merge, however, it does not produce a so-called merge commit. Instead, rebase produces a straight line of commit history without the "melting point" commit that is so typical for merge.
Rebase achieves this by temporarily putting aside any new commits that happened after the branches diverged. Then, any new commits from the base branch are applied to the HEAD branch; at this point, both branches look identical. Only then are the temporarily removed commits (the actual new commits that happened on the HEAD branch) reapplied (or "re-based").
What is meant by "long-running" or "long-lived" branches in Git?
Technically, all branches in Git work in the same way. Conceptually, however, many teams make a distinction between "long-running" and "short-lived" branches.
Long-running branches are meant to remain in the repository during its complete lifetime. They are typically branches that are shared among the whole team and are being merged into from other, short-lived branches.
Those short-lived branches are typically related to feature development or bugfixes. When work on these branches is completed, they are merged into a long-running branch and then deleted.
What are Submodules in Git?
A "Submodule" is a standard Git repository. Its only specialty is that it's nested inside another, parent Git repository. The most common use case for them is when including a code library. You can simply add the library as a Submodule in your main project.
A Submodule remains a fully functional Git repository: you can modify files, commit, pull, push, etc. from inside it like in any other repository.
How can you - with the help of Git - run a sanity check on new code before it is committed to the repository?
Git offers a mechanism named "hooks". These are custom scripts that can be configured to be run when certain events happen. As an answer to this question, it would make sense to write a "pre-commit" hook: this hook is triggered and run automatically before a commit is finalized. The script can be completely custom and, for example, check code to be compliant with agreed upon coding standards.