This repository is a list of git usecases that are commonly encountered during devleopment. Its primary goal is to show you how you can get into a delicate situation and train you how to solve it.
Recommended video:
https://www.youtube.com/watch?v=MyvyqdQ3OjI
Each test case is associated with a POSIX shell script that prepares a local repository located in the workspace directory.
Normally you will do the following for most use-cases:
- Run the associate .sh script
- cd workspace/<use_case_name>
- Solve the problem using git commands
-
Each script will clean the workspace and you will get a fresh start
-
A remote repository is configured in the .git-repos directory by using the file:// protocol. This means that "git remote -v" will output something like /home/alexander/git-training-usecases/.git-repos/.
-
If you don't have global username and email configured default values will be put for you in the workspace repos.
-
Git "lg" and "s" aliases are configured to use a pretty print git history and for status. Usage: "git lg" and "git s"
-
As a best practice and for security reasons you can run the exercises in a docker image:
docker run --rm --name git-exercises -v $(pwd):/git -it sashokbg/git-exercises /bin/zsh
-
Note that after running with docker you may need to manually clean the workspace and .git-repos directories with "sudo".
-
Some test cases run interactive rebases and generate a "fake_editor.sh" script that simulates the user input. This works using the GIT_EDITOR and GIT_SEQUENCE_EDITOR env variables.
- Add assertion shells scripts for all use cases to validate the solution
- Add git sensitive shell PS1 for the docker image
- Add collapsible hints and explanations for each case
I accidentally typed the git merge feat
command and now I am prompted a message for the merge.
I want to abort this merge.
Traps:
- If you close the file or save and close the merge will happenRun:
. ./abort_a_merge.sh
I finished working on my feature And I want to merge my code to main But I do not want to generate a merge commit In order to keep history clean and linear
Run:
. ./no_merge_to_main.sh
I work on a "feature" branch And a colleague of mine did a fix that is on "main" branch I want to "get" my colleague's code on my branch.
Run:
. ./get_most_recent_code_from_main.sh
I did a bad commit introducing a bug that got into production and is on "main" I want to quickly revert so that we can redeploy last version
Run:
. ./undoing_pushed_commit.sh
I did 3 bad commits introducing a bug that got into production and is on "main" I want to quickly revert them.
Run:
. ./undo_pushed_range_commits.sh
I did a wrong checkout And now my HEAD is in "detached" state
Run:
. ./detached_head.sh
I did a commit, but I want to add some files to it. I want to push my code to the remote
Run:
. ./redo_last_commit.sh
Do not forget to push your code to the remote. Attention trap ahead !
I worked on a feature And I had to quickly change a branch so I performed a "WIP" commit at one point. I want to clean this WIP commit before opening my merge request.
Solve for:
- I want to rename the wip commit
- I want to drop the wip commit
- I want to rename the wip AND the last commit to have (first, second, third, fourth)
- I want to fuse the wip commit with the previous commit
- I want to fuse the wip commit with the next commit
Run:
. ./clean_wip_commit.sh
I worked on a feature and did too many commits I wish to fuse them together before opening a merge request.
Run:
. ./too_many_commits.sh
I did two commits: one for backend and then one for frontend But I forgot to add one file in the backend commit
Run:
. ./edit_second_to_last_commit.sh
I am working on a feature and have not yet commited But I need to quickly change branch to main to fix an urgent issue.
Run:
. ./quickly_change_branch.sh
I have a non-tracked file called file2.txt This file exists in the "main" branch When I try to checkout "main" I encountered the following error
error: The following untracked working tree files would be overwritten by checkout:
file.txt
Please move or remove them before you switch branches.
Aborting
Run:
. ./non_tracked_file_checkout.sh
I squashed some commits But have not yet pushed to origin I want to revert my squash
Run:
. ./revert_squash.sh
I squashed some commits Then I pushed with --force I want to revert my squash
Run:
. ./revert_squash_pushed.sh
I worked on a feature and I wanted to rebase upon main
But instead I did a merge
Run:
. ./accidental_merge.sh
I edited the text1.txt file I want to rebase my feat branch onto main But another user edited the same file on main
Run:
. ./rebase_conflict.sh
I did one big commit that has too many changes I want to split it into three commits "split: 1", "split: 2" and "split: 3"
Run:
. ./split_commit.sh
Me, and a colleague worked on the same branch They commited a change on file1.txt I do a pull of the branch But it generates a merge
Run:
. ./pull_generates_merge.sh
I forked a repository from a remote Someone has pushed some new code to the original remote in branch main I want to get the latest changes from the original remote (The second remote is found at .git-repos/
Hint: Use the file:// protocol for the second remote and point at /.git-repos/multiple_remotes_get_main-upstream.git
Run:
. ./multiple_remotes_update_main.sh
I am working on a branch feat And I want to get the version of file "file1.txt" from the "feat/other" branch
Run:
. ./take_file_another_branch.sh
I have some files in my stash I want to see the state of "file1.txt" in my stash
Run:
. ./stash_fun.sh
I want to transfer current branch to new GIT repository as a new project
I want to ignore the dist directory
Run:
. ./ignore_dist.sh
I work on a repository that uses the same code as another repo I want to send my last commit to a colleague that is working on the other repo
Run:
. ./send_code_from_here.sh
I try to create a branch called "feat/my_feat" But it results in an error "refs/heads/my_feat" exists. Cannot create ...
Run:
. ./checkout_error_ref_exists.sh
I did some wrong operation And now I see the commits of my colleague as part of my PR
Run:
. ./foreign_commits_on_my_branch.sh
A colleague works on another repository that is not related to mine and have pushed a commit called "other commit". I want to get the content of their commit on my repo.
I added the second repository as a remote and pulled
And I receive the following error when trying merge
fatal: refusing to merge unrelated histories
Run:
. ./cannot_merge_unreleated_history.sh
I fixed two bugs that required editing the same file. I want to split it into two different commits. However, when I perform "git add -p" the two changes are added together.
Run:
. ./edit_hunk.sh
Run:
. ./merge_another_repo.sh
Run:
./merge_
git rebase --edit-todo
create a local branch that is named origin/develop