Merging and local problem resolution exercises for git
-
Fork repo at https://github.com/steveperkins/when-git-attacks and clone your fork
-
To see what branches are available, use
git branch -v -a
-
Check out the one-conflict branch. This branch has a conflict that prevents an automatic merge.
git checkout one-conflict
-
Merge the master branch into this branch
git merge origin/master
-
There are conflicts! Find out which files have conflicts.
git status
-
It’s a good start, but WHAT are the conflicts? Compare your version against the one in the
master
branch to find out.git diff
-
That’s more helpful.
<<<<<< HEAD to =====
shows what your changes were and==== to >>>>>> master
shows what themaster
branch’s changes are at the same line. Editpie.txt
so we keep "death metal" but remove "This'll be the day that I die". -
Stage your fix
git add pie.txt
-
Verify the file was added
git status
-
Notice we’re still in MERGING mode. We have to commit the changes (resolutions) to all conflicted files before the merge is considered complete. Commit the changes to complete the merge.
-
(Optional) Merge the changes back to the master branch
git checkout master
git merge one-conflict
-
Check out the
competing-line-conflict
branch. This branch has conflicts that prevent an automatic merge.git checkout competing-line-conflict
-
Merge the
master
branch into this branchgit merge origin/master
-
There are conflicts! Find out what the conflicts are.
git diff
-
Great, the master branch changed 'paper' to 'newspaper' at the same time we changed it to 'dead tree rectangle'. Change it to 'dead tree newspaper' so everyone's happy.
-
The
master
branch also changed 'fire' to 'off-by-one errors' at the same time we changed it to 'sharks with lasers'. Change it back to 'off-by-one errors'. -
Stage your fixes and commit the changes (resolutions) to complete the merge.
git add pie.txt
git commit -m "Merged from master"
-
(Optional) Merge the changes back to the
master
branchgit checkout master
git merge competing-line-conflict
-
Check out the
competing-file-conflict
branch. This branch has a conflict that prevents an automatic merge.git checkout competing-file-conflict
-
Merge the
master
branch into this branchgit merge origin/master
-
There are conflicts! Find out what the conflicts are.
git diff
-
The diff is not terribly helpful here. Let's try getting status instead.
git status
-
That's much more helpful. It shows that the master branch made changes to music.html at the same time we deleted the entire file. Git doesn’t know how to merge that - should the file exist or not? We have to tell Git whether we want to keep the file as it exists in
master
or confirm that we intended to delete the file. It's a Choose-Your-Own Adventure.- To keep the file as it exists in master, use
git
add
music.html
- To confirm that the file should be deleted, use
git
rm
music.html
- To keep the file as it exists in master, use
-
Whatever your choice, complete the merge
git commit -m "Merged from master"
-
(Optional) Merge the changes back to the
master
branchgit checkout master
git merge competing-file-conflict
-
Check out the
reverting
branch -
Let's edit JailhouseRock.txt. Make any changes you’d like.
-
Stage your changes
git add JailhouseRock.txt
-
Verify Git knows the file is ready to be committed
git status
-
On second thought, Jailhouse Rock is awesome already. Let’s revert the staged-but-not-committed changes.
git reset HEAD JailhouseRock.txt
-
Check the status
git status
-
Wait, what happened? Git unstaged the file, but didn’t discard the actual changes. That's good if you accidentally staged a change you wanted to keep but didn't want in the next commit. But we really wanted to do is completely throw away the changes to JailhouseRock.txt. To finish the job we have to use
git checkout
to discard local unstaged changes.git checkout JailhouseRock.txt
git status
-
Much better. Now our working directory has no changes! Note that
git checkout
only throws away unstaged changes - it has no effect on staged files.
-
Let’s edit LifeIsAHighway.txt now. Change Line 3 to "We all live in a yellow submarine".
-
Stage the changes
git add LifeIsAHighway.txt
-
Commit the changes and confirm with
git status
git commit -m "Added the missing submarine"
git status
-
Oh no, we edited the wrong file! We can’t use
git checkout
to fix this because the changes have already been committed. Let’s trygit reset
instead. The ~1 means "roll back to the commit 1 before HEAD". You could use another number instead.git reset HEAD~1
-
We're closer, but not there yet. Just like with JailhouseRock.txt,
git reset
removed the local (private) commit but didn't discard the changes. Let's try it a different way.git add LifeIsAHighway.txt
git commit -m "Added missing submarine"
git reset --hard HEAD~1
git status
-
Much better. Now our changes are nowhere to be found. It’s important to note that
--hard
ONLY works at the commit level, not the file level. When run at the commit level,git reset
will locally revert ALL changes in the commit, not just changes in a specific file.
-
Let’s edit TenThousandFists.txt. Change Line 1 to "Ten Thousand Fists Clutching Straws In The Wind".
-
Stage your changes, commit, and push
-
Crap! That was a terrible joke and shouldn't have been pushed to the remote repository! Let's fix it with
git revert
. First though, we have to find out what that bad commit's hash (ID) was.- Use
git log -1
to see the last commit's details, which includes the hash. 1 is just how many commits we want to see.
- Copy the first 5 or 6 characters of the hash
- Use
-
Run
git revert your-hash--here
to revert the commit identified by the hash -
Since the commit you want to revert is already in the remote repo (public), to reverse it
git revert
creates a second commit that nullifies the original commit’s changes. A text editor will open up for you to change the second commit’s commit message. The default message is fine, so just close the text editor. -
git status
now shows that the second commit is waiting to be made public (pushed to the remote repo). Go ahead andpush
.git push
-
The commit log now shows both the original accidental commit and the reverse commit that corrected it.