/when-git-attacks

Merging and local problem resolution exercises for git

Primary LanguageHTML

when-git-attacks

Merging and local problem resolution exercises for git

Table of Contents

  1. Worksheets
    1. Exercise 1: Merging

      1. Practice 1: Merging a line conflict
      2. Practice 2: Merging multiple conflicts
      3. Practice 3: Merging a file conflict
    2. Exercise 2: Undoing

      1. Practice 1: Undoing local (private), uncommitted changes
      2. Practice 2: Undoing local (private), committed changes
      3. Practice 3: Undoing remote (public) changes

Worksheets

Exercise 1: Merging

Practice 1: Merging a line conflict

  1. Fork repo at https://github.com/steveperkins/when-git-attacks and clone your fork

  2. To see what branches are available, use git branch -v -a

  3. Check out the one-conflict branch. This branch has a conflict that prevents an automatic merge.

    • git checkout one-conflict
  4. Merge the master branch into this branch

    • git merge origin/master
  5. There are conflicts! Find out which files have conflicts.

    • git status

    git status shows conflicted files but not conflicted text

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

    git diff shows conflicted text

  7. That’s more helpful. <<<<<< HEAD to ===== shows what your changes were and ==== to >>>>>> master shows what the master branch’s changes are at the same line. Edit pie.txt so we keep "death metal" but remove "This'll be the day that I die".

    conflicted text

  8. Stage your fix

    • git add pie.txt
  9. Verify the file was added

    • git status
  10. 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.

    • git commit -m "Merged from master" still in MERGING until a commit is made
  11. (Optional) Merge the changes back to the master branch

    • git checkout master
    • git merge one-conflict

Practice 2: Merging multiple conflicts

  1. Check out the competing-line-conflict branch. This branch has conflicts that prevent an automatic merge.

    • git checkout competing-line-conflict
  2. Merge the master branch into this branch

    • git merge origin/master
  3. There are conflicts! Find out what the conflicts are.

    • git diff

    git diff shows actual conflict text

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

  5. 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'.

  6. Stage your fixes and commit the changes (resolutions) to complete the merge.

    • git add pie.txt
    • git commit -m "Merged from master"
  7. (Optional) Merge the changes back to the master branch

    • git checkout master
    • git merge competing-line-conflict

Practice 3: Merging a file conflict

  1. Check out the competing-file-conflict branch. This branch has a conflict that prevents an automatic merge.

    • git checkout competing-file-conflict
  2. Merge the master branch into this branch

    • git merge origin/master
  3. There are conflicts! Find out what the conflicts are.

    • git diff

    git diff just shows unmerged file paths

  4. The diff is not terribly helpful here. Let's try getting status instead.

    • git status

    git diff just shows unmerged file paths

  5. 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 gitaddmusic.html
    • To confirm that the file should be deleted, use gitrmmusic.html
  6. Whatever your choice, complete the merge

    • git commit -m "Merged from master"
  7. (Optional) Merge the changes back to the master branch

    • git checkout master
    • git merge competing-file-conflict

Exercise 2: Undoing

Practice 1: Undoing local (private), uncommitted changes

  1. Check out the reverting branch

  2. Let's edit JailhouseRock.txt. Make any changes you’d like.

  3. Stage your changes

    • git add JailhouseRock.txt
  4. Verify Git knows the file is ready to be committed

    • git status
  5. On second thought, Jailhouse Rock is awesome already. Let’s revert the staged-but-not-committed changes.

    • git reset HEAD JailhouseRock.txt
  6. Check the status

    • git status

    git diff just shows unmerged file paths

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

    git checkout destroys unstaged file changes

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

Practice 2: Undoing local (private), committed changes

  1. Let’s edit LifeIsAHighway.txt now. Change Line 3 to "We all live in a yellow submarine".

  2. Stage the changes

    • git add LifeIsAHighway.txt
  3. Commit the changes and confirm with git status

    • git commit -m "Added the missing submarine"
    • git status
  4. 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 try git reset instead. The ~1 means "roll back to the commit 1 before HEAD". You could use another number instead.

    • git reset HEAD~1

    git reset un-commits local commits

  5. 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
  6. 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.

Practice 3: Undoing remote (public) changes

  1. Let’s edit TenThousandFists.txt. Change Line 1 to "Ten Thousand Fists Clutching Straws In The Wind".

  2. Stage your changes, commit, and push

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

    git log shows commit hashes

    • Copy the first 5 or 6 characters of the hash
  4. Run git revert your-hash--here to revert the commit identified by the hash

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

  6. git status now shows that the second commit is waiting to be made public (pushed to the remote repo). Go ahead and push.

    • git push
  7. The commit log now shows both the original accidental commit and the reverse commit that corrected it. git log shows reverse commit