What do you want to learn?
Skip to main content
Code School: Git Real
by Olivier Lacan and Gregg Pollack
Learn basic concepts of Git version control. Explore staging, cloning, branching, and collaborating with Git.
Start CourseBookmarkAdd to Channel
Table of contents
GIT, a distributed source control repository. I tried to picture clusters of information as they move through the file system. Were the commit messages like history books? I kept dreaming of a repository I thought I'd never see, and then one day, Git Real. You're watching level one of Git Real. I'm Greg Pollock, and in this level we're going to go over some of the real basics of using Git. The first time I got a gig working with the web, it was pretty typical. So there I was, first day on the job, and I needed to edit a website, I was told to FTP the file down, make changes locally, then FTP them back up. Which works fine until you find out there's somebody else who's also working on the project, and at times they may pull down the same file, make changes, and you both may try to upload and override each other's changes, and it's just a big mess. This is where you might need a version control system. So what is a source control repository and what does it do for you? Well the first thing it does is it deals with these sort of situations where you have two different people working on the same file, and you both check in that same file, it will try to merge that file for you. The second and more important thing is that it works as a time capsule, so overtime as you make changes to files and you check them into your source control, it keeps a time log so you have a complete history of all the files that have changed and even why they changed. You can see these are all the different versions in version control. Up until recently, most version control systems used a centralized repository. What this means is that you have multiple people and when they make changes and they make commits and store that in the history it's all going to one central repository, one server. Some version control systems, like Git, are distributed. This means that everybody has a complete copy of the repo. The nice thing about this is that you can make commits really quickly, you can work on it offline, and while everybody has a complete copy, that way if one gets destroyed, well everybody has a copy of the repo, unlike working with a centralized repository, well if you lose all your backups and the server goes down, well you're kind of out of luck. So now you know what it means when we call Git a distributed version system, or DVCS. Git was created by Linus Torvalds, when he was working on the Linux operating system, and he lost access to the proprietary version control system he was using. He wanted to create something new, something that was fast, that's distributed, and was good with working with large code bases, well like Linux. Most people with with Git on the command line, so in this course, we're going to be teaching all of the command line tools. That being said, there are still a lot of graphical user interfaces that you can check out, and if you want to install Git, or download some of those GUI's, you can go over to git-scm.com. Like most command lines tools, Git comes with a help system, so if you ever get stuck, you can run Git help, it'll give you a list of the commands. And then if you want to get more specific, you can type Git help and then the command you need more information about, and it'll have pretty good documentation. You're first step when you install Git is to set some basic configuration. You're going to want to set your user name, your user email because, well, what good is filling commit with awesome code If you can't take some credit for it, right? And we're going to run one last command to get some pretty colors on the output of our command line. So you've installed Git, and you're ready to work on your fist repository. Well, we're going to need a directory so let's create a directory if we haven't. We're going to go into that directory, we can work on some files at this point, and when we're ready to start the repository, we simply type git init. This is going to create a local Git repo for us. It's not up on any server, it's just local, it's actually stored in that .git hidden directory. You're never going to need to go into that directory, just know that's where it's all stored. Let's start working with Git, and we're going to talk about our work flow before we get into the commands. So Jane, our user here, is going to create a README file that README starts out as untracked. When we're ready to start tracking that file we're first going to add it to a staging area. We're getting ready to take a snapshot, then we're going to create our first commit. And a commit is basically like taking a snapshot of those files that we put on the stage. We then might work on our project more, maybe we modify the README and add a license, we're going to add those files to the staging area, and make another commit. So this is sort of the work flow for Git. You do a little bit of work, you stage it, you make a commit. Let's jump into the commands. One of the most important commands with Git is the git status command. This is going to tell you what has changed since your last commit. So we have run git status, we don't have any commits yet, it's going to tell us that we have one newly created file that's not being tracked. To start tracking it, we first need to add it to that staging area, we do that using the git add command, doing git add README. And if we do another Git status at this point, we're going to see that this file is now ready to be committed, it's currently staged. Now we're ready to make our first commit. We do this by running git commit -m, and then we describe what these changes do. So in this case create a README. We run that command, this creates our first commit which takes a snapshot of the stage, and that gets added to our timeline. If we run a git status at this point, we can see that there's nothing else to commit. There's no other changes or files that we've modified that we haven't committed yet. Git status also tells us that we are on branch master. All you have to understand here, is that we've got one main timeline at this point, and we're going to call it master. We'll get more into branches on level three. Now we're going to actually do some work on some files, we're going to modify the README and add a license. Now if we run git status, we're going to see that our tracked file, README has been modified. It's keeping an eye on that file, so it knows it's been modified. And we have a new file we need to add that's not tracked called license. We want to commit both these files, so we need to add them both to the staging area. We can do this by simply doing git add and listing both of the files, or we can do git add --all, which will add all new modified or deleted files to our stage. Now if we run git status again, we're going to see we have two files that are ready to be committed. So from here, we need to go back and do another commit. So here you can see we do get commit -m, now we can commit our changes off of this stage and specify what the commit does, in this case add license and finish README. This is going to create a snapshot and add a commit to the top of our timeline. Now we have two commits, but how do we list from the command line what those are? How do we look at the history? That's where the git log command comes in. So if we run it here, we can see we have our two commits listing the author, the date, and our commit message. As you can imagine, when you're working on a larger project, commit messages are very, very important, and so you want to try to be as descriptive as possible as to what they do. Plus it's good to keep in the present tense, not the past tense, I could have said, created a README file, it might be tempting to do that, but what you want to do is think about what the commit does, in this case create a README. Now we're going to go over some different ways to use the add command. As you saw, you can just simply list out files, you can use git add --all, git add *.txt will add all the text files in the current directory. If we want we can specify a directory, like docs/*.txt. We can also just add all the files in a specific directory and all of its sub directories by doing get add docs. And lastly, if you put quotes around *.txt, it's going to go add all the text files in the entire project.
Staging & Remotes
Staging & Remotes
Git. A distributed source control repository. I try to picture clusters of information as they move through the file system. With the commit messages like history books, I kept dreaming of a repository I thought I'd never see and then, one day, Git Real. (upbeat music) You're watching Git Real and this is level two where we're going to be talking about staging and remotes. So let's say you're in your local repo and you made a change to a file but you don't remember what that change was, like, for example, the license file here. To figure out what that change was, you can run the git diff command. You're going to see here that it's going to show you unstaged differences since the last commit. In the red you can see the line that was removed and in the green the line that was added. The diffs here in the command line aren't that understandable. Luckily, there are tools to make it easier to read, but let's go ahead and add that license file to our stage. Once we've added it to our stage, if we run git diff again, well, nothing's going to print out because there's no differences, since all of our changes have been staged. If we do want to get a diff on all of our stage changes, we can run git diff --staged and we'll get the same output that we did before. So if you do git status right now, we're going to see that we have that one license file that's staged and ready to get committed. But what if we staged stuff that we didn't mean to get staged? Because keep in mind, you might have a lot of modified files and you might want to take two of them and do them on more commit and take two more files and do on the next commit. So, how do we get things off the stage? Well, notice in this git status output it says "use git reset HEAD," and then the file name, "to unstage." Then, when we run the command you can see it says that we unstaged license. You might be wondering what that HEAD command is there. Well, HEAD refers to our last commit on the current branch or timeline that we're on. Now if we're running git status we're going to see that the license file is not on the stage but it still has its modifications. But what if we change our mind and we don't want those modifications? What if we want to reset it to the state that that file was in at that last commit or last time it was changed? Well, we can do that by doing git checkout dash dash, and then the file name. So if we do that and we run git status again, we're going to see that the file's been restored to its previous state. Now let's go ahead and make a change to the readme talking about how the cake is a lie. If we wanted to commit this change we'd have to add it and then commit it. Well, there's a shortcut. We can run git commit -a -m and the commit message. What this is going to do is it's going to add any of our tracked files to the stage and then commit them. Now the caveat here is that it's not going to add any files that we're not tracking. So if I created a new file and ran this command, well, it's not going to be included in the commit. There's going to be a time when you're running git where you're going to make a commit and then you're going to instantly regret it because you probably forgot to add a file or make some sort of modification that you wanted to be included. How do you deal with that? Luckily, we have this git reset command you see here, which will undo the last commit and move everything from that commit back into staging. So that HEAD command you see there with the little caret, what that saying is, move to the commit long before the current HEAD. So now if we run git status, you can see that our changes from that commit are now staged. I can make changed, add files if I want to, and re-commit. Another way to modify commit is to use the amend option. So, if we wanted to add that todo.text file to our last commit, we could simply add it to the stage, and then do git commit --amend, which is going to add it to the last commit, and then if we want, we can even specify a new commit message, which is going to overwrite our previous commit message. Here are the two commands we just went over. You've got git reset, which will roll back the last commit, and then you have git commit amend, which will add things to last commit. There's two more that you should know about. If you want to do git reset hard HEAD, that's going to blow away the last commit. So if you just went horribly wrong and you just want to blow it away, you run hard HEAD and then, if you want to undo the last commits, well, you just add another caret onto the end. So that's saying blow away the last two commits before the current HEAD. So up until now we've been working with just our own local repository on our computer, but how do we push that repository up to other people so they can contribute to it? Well, where the push and pull command comes in. So, here I am in my local master. I can push that to a remote repository and then other people can pull that repository down and start making changes. And then when they're done, they can push back up their changes. When we're dealing with remote repositories, it's all about the git remote command which we'll be going into in a minute. The other thing worth mentioning is that git doesn't take care of access control for you. It doesn't allow you to say just these people have access to this repository and just this group of people have access to this one. That's where you're going to need some additional software. You either might want to use a hosted solution, like GitHub or BitBucket, so they take care of access control for you, or if you want to roll your own, you can use something like Gitosis or Gitorious, and they take care of access control and all that configuration. If we wanted to store our repository on GitHub, we would create a GitHub account and then we'd create a new repository on GitHub. It would give us a form that looks like this. We would specify a name of that repository and specify a couple options. Then once we create it, GitHub is going to give us a URL. To push the GitHub we're first going to have to run git remote add origin. Origin is the name of the remote. We could give it any name. But usually we'd refer to our canonical repository, our official repository that most of our people are using for our project, as origin. So origin is what we're going to call it. And then we specify the URL that GitHub gave us. To get a list of all the remotes that our local git repository knows about, we can simply run git remote -v. Now, we haven't actually pushed our repository. These remotes are kind of like bookmarks, right? We're just bookmarking that this origin refers to this URL, or we might have multiple repos. Now, if we want to push our repository, we simply run git push, specify the remote repository name, which of course is origin, and the local branch we want to push there, which is master. Since we're using GitHub, it's going to ask for our GitHub user name and password to authorize us to push to the GitHub remote. Now, if you don't want to have to enter in your username and password every time you push, you're going to want to follow this link down here at the bottom which talks about password caching so you only have to do it once. So we've pushed our local repository up to GitHub and now, if we go back into our browser and refresh, we're going to see that GitHub now knows about our repository and all the data in it. On this page you'll notice there's a Commit button, also a history button. If we click those, we actually get the same information that we got previously from git log, we can view all the different commits inside our repo. So we've pushed our repo up to GitHub but how do we pull it down, how do we pull down from the remote? Well, that's when the git pull command comes in. That's what you're going to want to run when you know that other people have made changes, you're not the only person working on the project, and you want to get their changes. You run get pull. It will go up to GitHub. It'll pull down your changes and sync up your local repository. So we have GitHub as our canonical remote called origin, but it's not uncommon to have multiple remotes with a project. We might have a test server that runs our tests for us that we occasionally want to push our repo over there. We might have a hosting provider that has our production code in it. We might want to push our repo onto our production server so it can host the code. As we saw before, to add a new remote, use the syntax git remote add, specify a name, it can be any name, and then the address. To remove remotes, we simply do git remote rm and then the name. And lastly, to push our repository to remotes, we run git push -u and specify the name and the branch. Now, you might be wondering what this -u option does. Basically it makes it so that next time you run git push, you don't have to specify the name and the branch, you can just run git push. Lastly I want to talk about Heroku, a hosting platform, and the way they use remotes. So, if you have a Heroku account and you installed the Heroku gem and you're working on your code and you type heroku create, you can see it does a couple things for you, one of which is gives you a git repo ssh address. Now, before we were using a URL, GitHub gave us a URL. Well, a lot of times when you're working with git repos you might instead have a ssh address. As you can see here, Heroku already added a remote for us, it called the remote heroku. And now, if we want to push our code to Heroku, we simply write git push heroku master. That's going to push our local repository to Heroku and when Heroku gets the code, well, it's going to deploy it. One last thing before we finish level two. Remember these commands where you can roll back commits, blow away commits? Well, you only want to run them before you've pushed those commits, right? Because if you have some commits and you push and then you change them locally, it's kind of like you're changing history and as we all know, that's a very dangerous thing. So don't do it.
Cloning & Branching
Cloning & Branching
Git, a distributed source control repository. I try to picture clusters of information as they move through the file system with the commit messages like history books. I kept dreaming of a repository I thought I'd never see. And then one day, Git Real. (techno beat) You're watching Git Real. I'm Olivier Lacan. This is level three. We're going to talk about cloning and branching. So in level two, we saw that Gregg pushed the repository to GitHub, and now a new coworker called Jane needs to get those files. She will ask something like, "Where do I get those files?" And Gregg's going to simply say to her, "Just clone the repository." How do you do that? If you're using something like GitHub, you would go to the repository, get the URL that you saw from the repo. So you go back to your command line, type in git clone that URL, and it will create a local directory with that repository. It will be called the name that the repository was called. If you want to change that name to something else, you can say the same thing, git clone URL, and pass in a name like git-demo. The first thing git clone does is download the repository. The second thing is does is create a remote called origin and point it to the URL we passed it to. We can check that by simply running git remote -v and it would list all the remotes, so you will see origin and then the URL that we passed it to. And finally it will check out the initial branch, likely master, and set the branch right there and set the HEAD. So Jane is all set up, but she wants to start working on a feature. To do that, it's best to create a branch. So we're going to create a branch called cat. git branch cat will create that branch. But if we check with git branch, we can see we're still on the master branch. To move to the cat branch, we're going to need to git checkout cat. When we're doing that, what we're actually doing is switching timelines. We're not in the master timeline anymore. We're in a different timeline. We can do whatever we want and then move back onto master whenever we need to. We're going to run this command right here, and what it does is create a cat.txt file and inside of it put the word Schrödinger. Then we're going to add it to the stage, commit it, and just put a commit message like "Create quantum cat," and this commit will be added to our cat timeline, not to our master branch, but to our cat branch. If we run the ls command to list all the files in the current directory, you will see that we have the README.txt file that Gregg created and this cat.txt file we just created. Now if we move back to master using git checkout master and do the same command, we can't see any cat.txt file. It's not there. It does not exist in this timeline. Now, if we run git log, same thing. No commit. That create quantum cat commit is not there. Just to make sure we're not crazy, if we move back to the cat branch and do the ls command again, the cat.txt file is still there. We're not crazy. So let's assume we're done with that feature branch now, the cat branch. We're going to go back to master, git checkout master, and now it's time to merge those two timelines. It sounds really fancy, but it's actually quite easy. git merge cat. Now that we're on master, Git will merge the cat branch into it, and it will tell us that it fast-forwarded. It will say fast-forward. What does that mean? So when we create a branch and make one commit or several, and we do nothing on the other branch, it's very easy for Git to merge the cat branch back into master because nothing was modified on master in the meantime. And now that we're done, we can safely delete the cat branch by running git branch -d cat, and git will show us that it actually did that. Our next assignment is to work on the admin features for our application, so we need to create another branch to work on those. To do that, we're going to use a shortcut by simply doing git checkout -b admin. The -b over there creates a branch and then checks it out. Now we'll do a bunch of changes like create a dashboard.html file, add it to the stage and commit it. Add a users.html file and commit it also. And as you can see on this graphic over here, every time we do a commit, our HEAD moves with it. So there we are working on the admin branch, and we get a late night text message from our boss saying, "Ooh, there are bugs on master. "You need to fix them." So we have to stop what we're doing, git checkout master. We can run git branch to make sure that we are actually on master. And then we're going to pull from the remote repository to make sure that we have the latest changes. Then we're going to do our fixes by fixing the store.rb and product.rb files. And finally, we're going to push those changes back up to the master remote. Now that the emergency has been taken care of, it's time to move back to our feature branch. So we go git checkout admin. So we finish off our changes, git checkout master when we're ready to merge things back into master, and git merge admin. And suddenly you're in a weird editor. Don't panic, this is Vi. You may have seen this before, but just in case, here are commands at the bottom of the screen to navigate around Vi. It's simply Git asking you, okay, I made this commit message for you because I've seen what you're trying to do. You're trying to merge those two branches. But if you need to be more explicit, please add to this message at the top. As you can see, it wrote merge branch admin. You can modify this message if you want to and then when you're done, type colon w for write and q for quit to go back to your command line. Since we merged two branches with two sets of changes, Git had to do a recursive merge. When that happens, Git creates a commit right there when the branches are melded back together. If you look at your log, you will see that that merge commit was actually created in the log. It doesn't contain any files, but it simply says at this point, master and admin became one branch.
Git, a distributed source control repository. I try to picture clusters of information as they move through the file system were the commit messages like history books. I kept dreaming of a repository I thought I'd never see. And then one day, Git Real. (techno beat) You're watching Git Real, and this is level four, where we're going to be going over some collaboration scenarios. You know, what happens when things don't go as smoothly as Olivier showed you in the previous level? So here we have Gregg. He pushes up his source code to GitHub, and Jane of course wants a copy. As we saw, Jane is going to clone his copy off of GitHub, and then she's going to want to add some changes, so let's continue down that timeline. So she adds some changes. You can see there's two new files. We do a git add --all to add those files and then add store and product models. Then she pushes up to GitHub when she's done making her changes, and her commit is going to be represented by that little pink commit down there. Now let's jump back over to Gregg. See, Gregg is also working at the same time as Jane, and Gregg makes a commit, basically adds a change to the readme. So now we have Jane's commit which is sitting up on GitHub and Gregg's local commit which is sitting on his local repository, and they are different. So what do we do at this point? If Gregg tries to push to GitHub at this point, well, he's going to be rejected, because, as you can see here, the tip of his current branch is behind the remote branch. So what we'd have to do here is we can simply do a pull first and then a push, and it would work. It's important that we know what's going on under the hood when we run this pull command. So the first thing that pull does is it fetches or syncs our local repository from the remote one. It's the same thing as doing a git fetch command. So in this case, it's going to copy down Jane's commit into our local repo. However, it's not actually going to update any of our local code. If we looked under the covers here, we would see that in our local repo, we actually have a branch called origin/master. That's our remote branch. And now the second step with pull is that it merges the origin/master with master. It's the same thing as running git merge origin/master. So just like you saw with the previous level, when we try to do a merge for two different branches that have different commits, it's going to pop us straight into an editor where we have to create a merge commit. In this case, our message says that it's merging branch master from our remote repository. Once we save from that editor, it's going to give us some output from the pull command and tell us that it did a recursive merge. If we look back at the timeline, we're going to see that we had two branches and they merged on the merge commit. You might notice here, though, that we have our local master still has that merge commit, but the origin/master doesn't yet know about Gregg's change and about the merge commit, and it's not going to know about it until we do git push. At that point, origin/master points to the same master branch and everything's been updated. And now if we check the log, we can see there's our merge commit. Now, some people aren't big fans of merge commits. Some people think they pollute our repository, pollute our history, because if you have a lot of collaborators, you might have 10 things that changed and maybe three or four of them are the merge commits. It can start to get pretty sloppy. And in a later level, we're going to be talking about rebase, which is one way to get around doing these merge commits. But for now, let's move on to another scenario. So Gregg and Jane once again are working on the same code at the same time, except this time they happen to be working on the same file, the same readme. Gregg thinks the cake is a lie and Jane thinks the cake is telling the truth. And they both edited that same file. Jane committed her changes and pushed to GitHub, and Gregg just committed locally. So now you can see that we still have two different commits, but they're on the same file. Hmm, what's going to happen now? So when Gregg does a pull, it does two things. Remember, it syncs the repository, pulls down the changes, pulls down Jane's commit, and then it tries to merge, but the merge was not successful. We have a conflict. It tells us there's a conflict in readme. So we're going to have to edit that readme. Since it spit us back out in the command line, if we do a status, we can see that, well, we have to edit this file and then make a merge commit. So if we jump into the readme at this point, we're going to see what kind of looks like a diff. Inside this diff, it has our local version. That's the HEAD. And we have Jane's version. We're going to need to edit this file manually to fix it. So we're going to delete all the extra text and make it so that the cake is a lie, because that's what we think, well, it is a lie, and then we just call git commit -a. We're going to leave off the message because it's going to boot us back into an editor. It'll give us a good commit message and it even lists the conflicted files that we fixed. Once we save that, our tree, again, looks something like this with our merge commit, and once we push, once again, the origin/master syncs up with our local master.
Git. A distributed source control repository. I try to picture clusters of information as they move through the file system where they commit messages like history books. I kept dreaming of a repository I thought I'd never see. And then one day Git Real. (electronic music) You're watching Git Real and this is Level 5. We're going to be talking about Remote Branches and Tags. So in level 3, Olivier taught you about local branches. But what about remote branches? There's going to be times where you have a branch, let's say an admin branch, and you want other people to be able to work on it. You're going to need to be able to push that branch remotely so other people can pull it down and work on it and continue working on it until it's ready to merge back into master. Also, just a good practice, if you're working on a branch that's going to last longer than a day, you might want to back it up, and you can back it up, of course, by making it a remote branch and pushing it to GitHub. In our case we want to start working on a shopping cart. So we create a shopping cart branch and then to push it to GitHub we simply run "Git push origin shopping cart." So that is going to link the local branch to the remote branch and start tracking it. Then maybe we'll get some work done on the branch, we'll add the cart, we'll do a commit and then when we do push, because it is a tracking branch, it knows to push the local shopping cart branch to the remote shopping cart branch. If we jump back over to GitHub now and click that button right there, we're going to see a list of all the branches, all the remote branches, right here. We can click on shopping cart and we can see the last commit of the shopping cart branch and all the files. So we created a branch, we push it up to GitHub, and then maybe I tell my coworker, "Hey, Jane, I started the remote branch for shopping cart, if you want to work on it, go ahead and grab it." So what do things look like from Jane's perspective? Well the next time she does a pull, it's going to show her in the output that we have a new remote branch called shopping cart. If she does git branch, she's not going to see it as a local branch yet, but if she does git branch dash r, she's going to be able to see all the remote branches. She's going to run git check out shopping cart to start working on the branch, and it's automatically set up as a tracking remote branch. So from here, she can make her changes and when she's done she can git push to that remote branch. One of the most useful commands for working with remote branches is the git remote show command. So then origin, of course, is our remote name. So this is going to show us all of our remote branches and whether they're tracked or not. It'll show us all the local branches and which remote branches they merge with. And lastly it'll show us all the local branches configured for when we do a git push. The cool part about this is it even goes out to the server and checks to see if any of our local branches are out of date, in which case, here, we can see that our shopping cart is out of date. Remote branches, just like local branches, don't last forever. You might get done with a feature. To delete the remote branch, you're going to run get push origin colon and then the branch name. This is only going to delete the remote branch though. You're still going to have a local branch for shopping cart. So we're going to also want to delete that. So we run git branch dash d shopping cart. Uh oh, and it's not letting us delete that branch. It says that there's some commits that we haven't merged anywhere. That's kind of a cool feature of Git. If you try to delete a branch and there's commits that haven't been merged anywhere, well it's going to say "hey you're deleting changes that you might want." So it gives you a warning. But if you really do want to delete the branch you can just do capital D and it will delete it. So Jane is the one that deleted the remote commit but Greg is the one that created it in the first place. So what happens when he tries to push to that remote that doesn't exist anymore. Well, let's take a look. So Gregg is working on that branch, he commits something, then he tries to do a push. Well, nothing happens. Because the remote doesn't exist, locally, it's just a remote branch. To figure out what's going on, Gregg might run git remote show origin. Here he's going to see that "oh look that shopping cart branch is stale, somebody deleted it." Okay, to remove that reference, he's going to want to run git remote prune origin just as it says and it will clean up all the old stale branches. This command is something you probably want to run every once in a while if you're on a large project that has a lot of remote branches that get deleted at some point. It's going to remove all of those stale references. Let's say one of our remote branches is a heroku-staging server. We called it "heroku-staging." The thing about heroku is that it only deploys the branch which is named master. Right, so, if we have, let's say, a staging branch, and we do a git push heroku staging staging, well, it's going to try to push a remote branch called staging and nothing's going to get deployed. Because as I mentioned a minute ago, heroku only looks for the master branch, it only deploys from the master branch. In this case we would run git push heroku-staging staging master. What that's going to do is link up our local staging branch to the remote heroku master branch. So when we push to it, it's going to push from staging to master and deploy. So now that we've talked about remote branches we're going to talk a little bit about tags. Tags are basically a reference to a specific commit. It's a good way to sort of jump back to that state of what the code was in at any given time. A lot of people use it for release versioning, right, so when we have our code in a good state we might tag it Version 0.1. So to list out all the tags we can just do git tags to check out that tag and go back to what the code looked like when we tagged it. We do git checkout and then the tag name. To add a new tag we can simply do git tag dash a. Add the tag name. And then give a tag description. And lastly to push our tags we actually have to specify push dash dash tags and that will push it to a remote. Otherwise, the tags will just remain local. Now if we go back over to GitHub and click the branch button you're going to see that there is a tags tab. If we click that we're going to see a list of the tags for our current repository. We can click one and then we're brought to a page where we can see the state that our code was in when we tagged it.
Rebase Belong to Us
Rebase Belong to Us
GIT, a distributed source control repository. I tried to picture clusters of information as they moved to the final system. Were they commit messages like history books? I kept dreaming of a repository I thought I'd never see. And then, one day, GIT real. (electric, dramatic music) You're watching GIT real and this is level six where we're going to be talking about rebase. So you remember, in previous levels we talked about merge commits not being so great. You've got merge commits from local branches, merge commits from remote branches and it might seem like it's polluting your history. That's not so good . But there's an alternative to doing these sort of merges with merge commits and that's called Rebase. So, let's show back into this scenario we were at before where we have Jane's commit up on github which is different than gregg's commit that's on local. So instead of doing pull and push, we're going to do fetch and then rebase. So, if you remember, when we do fetch, that goes to github and pulls down any changes but doesn't merge them. So, if we took a look at our current branch, it looks something like this. We have master and origin/master. Git rebase does three things. First, it's going to move all changes to master which are not in origin/master, so it's going to take gregg's commit and move that to a temporary area. Then, it's going to run all of the origin/master commits one at a time. So there it goes. We run that commit on master. And then third step it's going to run all the commits in the temporary area, on top of our master one at a time. So, just like that. Now, as you can notice, there's no merge commits here. It's just one after the next after the next. Back in level three, when we first learned about local branches, remember we had this admin branch and then we had to go back and fix some bugs on master, and then we had to merge the admin into master. Well, how might we rebase instead of doing merge? Well, what we might do is first check out the admin branch, then run get rebase master, this is going to first run the master commits and then it's going to run our additional admin commits. Then, the next step is to check out the master branch and then merge from the admin back into master. All this is going to do is one of those fast-forwards that we talked about. So it's just going to run the same commits one after the next after the next and we're good to go. Even if we're running rebase, we still might run into conflicts. So let's take a look at a scenario with a conflict. As you can see, you're up on github, we have an extra commit as we do locally and those two extra commits both modify that same readme file. Okay. So step one, we fetch from github, step two, we run git rebase, that's going to take all of our new commits for master, move them into a temporary area, then it's going to run all the origin master commits, and then finally it's going to run all of the commits in the temporary area one at a time, which, of course, is going to lead to a conflict. So here's what you see when rebase runs into a conflict. You can see it's asking us to fix the merge conflict in readme.text, and when we resolve the problem, run git rebase continue. However, if we want to skip the patch, we can run git rebase skip or if we want to roll back and pretend we never rebased, we can just do git rebase abort. If we want to get status, we would see that we're not on any particular branch. We're in the middle of the rebase. So after we edit the readme, we do git add readme, then we type git rebase continue and it continues applying the commits. If we take a look at the commit messages at this point, it would look something like this. So, once again, you can see there is no merge conflict, it's all just one after the next and it feels a bit cleaner. I'm not saying that rebase is the answer all the time. Sometimes you might want to rebase, sometimes you might want to merge. If you're dealing with a branch that's been around for a long time and that has a lot of changes, you probably want to do a merge instead of a rebase. That way you've got, you know, you know exactly when it got merged back in and you have a log of everything that got changed in that one merge when it came over. But yeah.
History and Configuration
History and Configuration
Git, a distributed source control repository. I try to picture clusters of information as they move through the file system, were the commit messages like history books. I kept dreaming of a repository I thought I'd never see. And then one day, Git Real. (techno beat) This is Git Real. You made it to the final level. We're going to talk about history and configuration. In the previous levels, we've used git log repeatedly to see a list of our recent commits. Those commits usually include the SHA hash and then the author, the date, and the commit message. The output from log is not usually the most easy thing to read, so we're going to go over a couple ways to improve the output. The first thing you should do if you haven't already done it is to turn UI colors to true. It will emphasize your commit hash every single time. You can also format the output for the log differently. So if you pass in git log --pretty=oneline, it will display one commit per line with the SHA at the beginning and the commit message right after. Even better, you can format the output of the log exactly how you want it by using format. You can use a bunch of placeholders to organize the output of each commit in your log. If you want to look at what each commit changed in the log output, you can use the git log --online -p for patch output, and that will show you what lines were removed and what lines were added for the files that were modified during each commit. Git log --online --stat will show you how many insertions and deletions were made for each file included in each commit. If we use the graph option, we will get a visual representation of the branches and the commits on them so that maybe you could see your merge bubbles. It's not always useful to have the entire log history right there, so what you can do is specify a range between a certain date and another date where you want to see the log. You can also limit the log output based on time using flags like until a minute ago, since one day ago, since two weeks ago, or between a month ago and until two weeks ago. As you saw previously, git diff can be really useful to see what has changed since our last commit. You can see the removed lines and the added lines in the files that were included. Git diff HEAD does exactly the same thing as git diff. If you want to see the difference between the files now and two or three or five commits ago, diff gives you the following commands to do that. You can also compare two different commits, such as the second most recent against the most recent. If you remember those commit SHAs that we saw in the log, you can use those, as well, to compare between two commits specifically by naming the SHAs. Sometimes you'll see these SHA hashes abbreviated on places like GitHub. You can also use these abbreviated SHAs to run diffs and you can also use branches to run diffs. So for instance, you could say git diff master bird if you had a bird branch you wanted to compare against. Finally, just like git log, you can use time-based ranges for git diffs. When projects go on for a while, sometimes you come across a change that has been made in a file that you really can't understand, and a good tool for that is git blame. You can run git blame and file name to see all the changes on each line and who made them when and which commit created that change. So let's move on to some more advanced configurations. There may come a time in a project where you need to work on a specific folder, but you don't want to include this folder inside the repository and share it with your other coworkers. In this case, we have an experiments folder that we want to exclude from our local repo but not exclude from elsewhere. What we can do is put that experiments folder inside of the .git/info/exclude file. Just put the name of that folder in there and when you run git status, you won't see that folder anymore. You can also use exclusion patterns in that file. You can specifically exclude the tutorial.mp4 file or all files that have the mp4 extension. You can exclude a whole folder, like we saw. You can also exclude every log file inside of the log directory. Speaking of logs, nobody should ever include log files inside of a repository. Why? Because they always change differently depending on who's using the application. So what you want to do is use, instead of an exclude, a gitignore file, which will ignore all log files not just in your local repository, but also for everybody else. So here we have a server log file that we want to not have in our repository. We're going to put logs/*.log so that any log file in that logs folder will never get included, and then we will run git status. As you can see, there's no log files showing anymore. And then just commit that. One thing we haven't covered up until now is how to remove a file from your repository. You can use the git rm command and then pass in a file or a folder. If you do git rm readme, it will remove your readme and then add that change to the stage, and you simply can commit remove readme and that file will now disappear. But in the case of log files, if you were already tracking the file, you don't want to delete it from your file system. All you want to do is tell Git stop caring about this file. Stop tracking it. To do that, you can use git rm --cached, which will stop watching for changes, stop tracking the file. After that, if you do git status, you will see that it's deleted the same way, but it won't be deleted from your file system. And after you've untracked that log file, you can do the same gitignore and commit and no more log files will be tracked. In level one, we saw some basic configurations for the user and the email. Let's look at more configuration details that you can have. You can configure a specific merge tool if you want to see merge conflicts in a better way. There's also a very useful feature if you're working with Windows or Unix systems that will convert files to the Windows or Unix formats once they're committed. Then when you run config --list, you'll see your global email first and then the email specifier for this repository second, which overrides the previous one. You can verify this by running git config user.email inside of your repository and it will show you which email is set for this repository, then it will show you which email it's currently using. If you remember the log formats we went over in the beginning of this level, there's a bunch of really tricky options you can pass to them, and it's really hard to remember that all the time. What you can do, though, is create an alias to these log output formats. So for instance, you would use a special mylog format that triggers log pretty format and has a custom format. Another popular output format for git log is the lol format, which will show you a graphical output, just like we saw before. Here we have a mylog format that gives us a nice output without having to pass any options. You'll notice as you use Git every day that the same commands keep coming up over and over again. You use git status, you use git checkout, you use git branch and commit. But you can alias those commands to shorter ones by doing the following. So now if we simply type git st, we can see the git status output.
Released1 Aug 2012