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.
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 snensitive 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
cd workspace/abort_a_merge
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
cd workspace/no_merge_to_main
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
cd workspace/get_most_recent_code_from_main
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:
./undo_pushed_commit.sh
cd workspace/undo_pushed_commit
I did a 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
cd workspace/undo_pushed_range_commit
I did a wrong checkout And now my HEAD is in "detached" state
Run:
./detached_head.sh
cd workspace/detached_head
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
cd workspace/redo_last_commit
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
cd workspace/clean_wip_commit
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
cd workspace/too_many_commits
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
cd workspace/edit_second_to_last_commit
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
cd workspace/quickly_change_branch
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
cd workspace/non_tracked_file_checkout
I squashed some commits But have not yet pushed to origin I want to revert my squash
Run:
./revert_squash.sh
cd workspace/revert_squash
I squashed some commits Then I pushed with --force I want to revert my squash
Run:
./revert_squash_pushed.sh
cd workspace/revert_squash_pushed
I worked on a feature and I wanted to rebase upon main But instead I did a merge
Run:
./accidental_merge.sh
cd workspace/accidental_merge
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
cd workspace/rebase_conflict
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
cd workspace/split_commit
Me and a colleague worked on the same branch They commited a change on file1.txt I do a pull of the branch But and it generates a merge
Run:
./pull_generates_merge.sh
cd workspace/pull_generates_merge
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
cd workspace/multiple_remotes_update_main
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
cd workspace/take_file_another_branch
I have some files in my stash I want to see the state of "file1.txt" in my stash
Run:
./stash_fun.sh
cd workspace/stash_fun
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
cd workspace/ignore_dist
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
cd workspace/send_code_from_here
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
cd workspace/checkout_error_ref_exists
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
cd workspace/foreign_commits_on_my_branch
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
cd workspace/cannot_merge_unreleated_history.sh