Skip to content

Latest commit

 

History

History
109 lines (63 loc) · 6.3 KB

3-merging_and_history.md

File metadata and controls

109 lines (63 loc) · 6.3 KB

MERGING AND COMMIT HISTORIES

It's good practice to commit regularly and fully utilize branches, but frequent commits are useless without being able to look over previous commits, and branches are a hindrance without merging.

Commit histories

This continues straight from the previous file, but you can really do it anywhere. Take a look at the log of all the changes made to this branch.

git log

Let's look at one log entry in more detail.

commit 9b034e816d407738ae152c336f0e4071d1c2fe3c
Author: Ethan Soergel <esoergel@gmail.com>
Date:   Wed Jun 5 22:57:57 2013 -0400

    initial commit

This shows some basics about the commit - who made it, when, and the commit message. This is why it's a good idea to have a helpful commit message; looking back over commits, you (and others) can see what each commit was, and may be able to get a better idea of when things were added.

The fist line says "commit" and then has a string of 40 characters. This is a SHA1 hash of the entire state of the repo at the time of that commit. This hash is pretty much guaranteed to be unique - if you change so much as one character, this string will change completely. Git uses this hash as the name for that particular commit, and these hashes are used to verify the integrity of the repository.

Copy the hash from your last commit (or any other one), and run the following command:

git show <40-character-hash>

This will give you some details about the commit, including what changes were made.

You can checkout any commit by referring to it's hash.

git checkout <40-character-hash>

Git will let you know that you're in a "detached HEAD' state, and if you run git branch, it'll show that you're on "(no branch)". As before, you can turn this into a real branch called "oldcommit" by running

git checkout -b oldcommit

If you already know you're going to want a real branch when you check out an old commit, you can do it in one step like so:

git checkout -b oldcommit <40-character-hash>

At this point you should be comfortable making and deleting branches, and committing changes.

Merging

Okay, so you've made some changes on a branch, and you're ready to incorporate them elsewhere. Get on the branch where you'd like to incorporate the changes, and then merge in the branch where you made the changes.

If you followed along with the previous file, you should have a branch called "myfeature" that's forked off of "develop". Let's merge the additions from "myfeature" back into "develop"

git checkout develop
git merge myfeature

Easy, right? Because there have been no changes to develop since the fork was made, this merge should be totally painless. In fact, most merges are. This merge looks something like this:

a-----b---------------e----   develop
       \---c----d----/        myfeature

Starting from the left, after commit b, the myfeature branch was created. There were some changes to myfeature, but none on develop, so when the merge happens, git knows it can just apply all the changes from myfeature right on top of develop, as if they happened on the develop branch like so:

a-----b----c----d-----e----   develop

The only time there'd be some confusion is in cases where the commits were made next to each other, not sequentially.

a-----b------e--------f----   develop
       \---c----d----/        myfeature

In this case, git doesn't necessarily know in what order to apply the changes, but the order typically doesn't matter, and all changes are applied. This usually still isn't a problem unless there are changes in the same place in the same file. In that scenario, git will tell you you've got a merge conflict, and you have to manually resolve the conflict. Let's do an example.

You may have noticed another branch called problem_branch in the repository. This branch forked off an earlier version of develop, and made some changes that will conflict with what's currently in develop. The conflict will occur in problem_file.txt. Feel free to checkout both branches and read the files to see what they look like now. You can also look at them by checking out earlier commits (or browsing the current state of this repo on GitHub. Let's make that merge conflict happen!

$ git branch
* develop
  master
  problem_branch

Good, we're on develop, where we want to incorporate the changes. Merge in the problem branch.

$ git merge problem_branch
Auto-merging problem_file.txt
CONFLICT (content): Merge conflict in problem_file.txt
Automatic merge failed; fix conflicts and then commit the result.

Craaaaaap. Okay, let's survey the damage. Open up problem_file.txt. Here's the relevant portion:

Fap small batch yr raw denim wayfarers cornhole four loko, chillwave chambray banjo McSweeney's.
<<<<<<< HEAD
Wolf seitan yr salvia, tote bag next level readymade gluten-free art party.
=======
Helvetica jean shorts ugh beard, 90's church-key High Life.
Photo booth authentic flexitarian Bushwick, kale chips Portland biodiesel.
>>>>>>> problem_branch
Odd Future cray master cleanse, actually tattooed banh mi shoreditch Tonx.

Git marks the section where there's a conflict. "<<<<<<< HEAD" marks the start of the version that appears in HEAD (the branch you're currently on), "======" indicates where the version from problem branch begins, and ">>>>>>> problem_branch" marks the end of the conflict. In this case, the file just appears to be a list of sentences randomly generated from hipsteripsum.me, so we can just remove the three lines added by git and add/commit the changes, thus marking the conflict as resolved.

git add problem_file.txt
git commit -m "resolved merge conflict in problem_file.txt"

Run git log and you can see that the commits from both branches appear in the history.

Okay, that's the basics of working with git locally. If anything is unclear, or if I'm missing anything please let me know. You should be able to make changes, look at previous versions, hop around branches, and merge changes at this point.

The next files talk about some techniques to deal with having multiple contributors, and using git as part of a team (that's when branching and merging become essential). Continue on to collaboration concepts.