 Okay, so, you may have noticed that sometimes we make mistakes and we want to undo them, whether that's in life or in files or whatever. In the case of files on a computer system, it turns out that there are some really good ways of undoing things. In particular, a version control system is a tool that you can use to manage your source code, your text files, your configuration files, whatever you want really, so that you can maintain a persistent history of the changes to those files. So, whenever you want to track changes over time, a version control system is probably the place you want to start. In addition, a version control system, you can use to share changes to different users, right? So, if you make some changes to a file over time and Anish makes some changes to like a similar set of files, you might want to be able to combine those changes so that the two of you can work on the same project and you can see what each other has done. There are a ton of version control systems out there that work differently, that give you different features that are harder or easier to use, that are different assumptions about what kind of files you're working on. In this particular lecture, I'll focus on a tool called Git, which is one of the more common version control systems that also supports things like working with multiple users, multiple machines, and it's also one that's very well supported by online platforms for sharing source code and those kinds of things. But you will probably find that some of the concepts carry over to other systems as well. In particular, I'd recommend you take a look at a tool called Material, which many people tell to sort of git without all the weird parts. Whether or not you agree with that is for you to decide by looking at it, but in general, we're going to be using git in all today and whether you want to explore other things, you can do that anytime. For those of you who may have heard of git from before, actually, how many of you have heard of git? Nice, how many of you have used git? How many of you think that git is dark magic? I sort of do. Yeah, so that's all right. So, there's this common adage on the Internet that nobody understands git. It's really just about typing random commands that you find on the Internet into your terminal, which we all know is a great idea, and then they sort of maybe do the right thing. So the goal of this lecture is going to be to teach you a little bit more about how that works, why those commands do what they do, and sort of the mental model that you should have in mind when working with version control systems. At the very, very basic level, the thing to learn about git is its data model. How it thinks about the files that you're storing and the history that you're storing. Once you understand the data model, a lot more of the commands that you operate on the history of versions is going to become a lot clearer like what's going on behind the scenes. The core thing in git is something known as a commit. So a commit is basically a snapshot point in time of the current state of whatever folder you're looking at. So whenever you are using a version control system, it's usually based on some folder and everything underneath it, and it's sort of a snapshot of that folder, sort of frozen in time version of all the files that are in that folder. And a commit, every commit in git has a unique name. It's known as a hash, so it looks a bit like this. So this thing right here is a commit hash. Every single snapshot that you capture, every commit has one of these hashes, and they are guaranteed to be unique in the confines of any given git repository. Commits also have a bunch of other information. It records things like who authored that commit, so who made the snapshot. It usually includes some kind of message that describes that snapshot. Like why did I choose to take this snapshot right now? It also has the hash of the previous commit. So you sort of get a timeline of these are the changes that have happened over time, and which changes depend on other changes that have happened before, right? And the commit also represents basically the difference from the previous commit that you made. In particular, here, so if I type git log, it shows me the log of changes that have happened to this directory, and you'll see who made each change, what the name of each change is, and when that change was made, and the commit message. And in addition, if I do ignore a little bit of what this kind of says, here this is a diff showing what is different between the previous commit and this commit. So you can think of these snapshots as basically capturing which things changed from one point in time to another, right? So these green lines are lines that were added. The red lines are lines that were removed. In reality, git actually stores the full snapshot, it does not just store these differences, but you can think of each commit as sort of applying a difference to the thing that came before, and that's why it needs to remember what came before. So initially, whenever you start out with git, this is the repository we used in the shell scripting lecture, so it just has a bunch of random files in there with nothing particularly interesting in there. Whenever you want to start tracking something we get, you create a repository. So all repositories are basically where git keeps all the information about the folders it's managing, and you start one with git in it. You give it then a folder. If it doesn't exist, it's going to be created. In this case, I already have a folder, which is this through bar folder that I'm currently in. So I'm going to say to get start a new repository in this folder. And what that does is it creates in this directory a .git folder that has a bunch of hidden information that git uses to track history and those kinds of things. And you'll notice that my prompt, which I've configured, like we talked about in the command line environment lecture, to show me information about current version control status, what exactly is shown in this prompt you will hopefully understand by the end of this lecture. You should not expect to understand it now, but just notice something appeared that made it recognize that this folder is now version controlled. So now that I have... Actually, let's start with an empty one first. So I'm going to see the attendee. So this is now a directory that only has the git. There's no files in here. The only thing that's in there is the hidden git directory. There's nothing else in there. And let's see what git thinks about this directory. So there's a command. So all the git commands start with git command. In this case, status is a command you're going to be using a lot. It tells you what git thinks is the state of the current directory. So in this case, git status actually tells us a lot of things that are going to teach us what git is doing. It says we're on the branch master. It says there are no commits yet. And it says that there's nothing to commit. Let's walk through each of those in order. First, on branch master. Well, it's really annoying if we always have to use these long strings of characters. If I had to tell you, like, I'm currently on 522e6c, et cetera, it would be really, really annoying. So instead, git has a way of naming these things. And so a branch is a name. The default branch is master. What a branch is is really just sort of a name that points to a commit. Initially, it points to the empty commit because initially your repository is empty. And then every time you make a change, a new commit is made. It has its new sort of hash in its unique. And then master is updated to point to that updated commit name. And so as you go along, where master points is going to change. Master is always going to be the latest change on the branch called master. And you can have multiple branches if you want. There's also a special name called head. So if you notice over here, I said, ignore what grammar parts does. You said, I wrote head here. Head is always the current commit. Whatever the current commit is, that's what head is. You can also make your own names. So if I do git branch, I can name a new branch called foobar. And I could give it something like this thing to point the name foobar at this commit. If I then made additional changes to the underlying repository, then the foobar branch would not be changed and would still be pointed to that commit, unless I chose to update it to point to something else. By default, you're on the master branch. What being on a branch means is that whenever you make a new commit, that branch name is updated to point to the latest commit. So if I were to make a commit in this directory, master would be updated to point to that, but any other branches would not be changed. They would retain whatever they were previously pointing to. No commits yet is sort of self-explanatory. We have created a new repository and there are no commits in there, and we have taken those snapshots, and therefore there are no commits. And this third line, this is nothing to commit, actually is really, really interesting. As I mentioned, every commit sort of contains the difference that you made. It sort of contains all the changes you made since the last time you took a snapshot. But how do you construct one of these differences in the first place? How do you save what it is you want to include in a commit? Of course, you could assume that if I have a bunch of changes in the current folder, I always want to commit the current snapshot of all the files. I want to take a snapshot of everything that's there. You could do that, but sometimes there might be some things you don't want to include in a commit. I might have some files in there that are just sort of temporary. I might have made some changes in a file that aren't really ready to be committed yet. I just want to commit other parts of that file. Or sometimes I might have made multiple different changes. And I want to break them up into different kinds. Maybe with different messages to sort of explain why I made each change. And so that it's easier for someone else to look at my change. Instead of seeing just one large change, they can look at multiple smaller ones. So it makes sense that sometimes I only want to make a commit of parts of the changes I've made. And so this last line is basically telling us about that feature. You have a way in Git to say that I want to stage this change for the upcoming commit. Basically I want to say that this change should be included in the next commit. To give you an example of this, let's see. So I'm going to first make a commit with the message, this is the first commit. So this is just the sort of first commit and the repository contains nothing in it. I'm just saying this repository starts out empty. So I've created a commit now but that is kind of false. Oh, I may need to include something. Fine. Close your eyes and ignore this for a second. This didn't happen. You don't know what that is. Great. Great. So the directory is empty and Git stages now says I'm on branch master, there's nothing to commit. Now, because I made a commit that you can sort of ignore, it doesn't say no commits yet because there are commits now. So in this repository now, you add a new file, right? So I'm going to use spin and I'm going to create a file called low and in that file, I'm going to say world. So now it gets data says untracked files. Hello. Nothing has been added to commit but there are untracked files. So in this case, I can use git add to add a particular file to the commit that I'm about to make. This is saying take all the changes I've made to the file to low and just stage them to be included in the commit I'm about to make. Similarly, let's say that I now make a change to low. I say foobar down here and then I look at git states. What's it telling me? Does changes to be committed, new file hello, changes not stage for commit, modified hello, right? So I added hello to the sort of stage, the stage set of changes for the upcoming commit and the line where I added foobar that line was not part of what I added. So what it's telling me is that it has included part of the file but there are also changes that it will not include in the upcoming commit. And I can look at those by saying git diff, right? So git diff tells me these are the things that have not yet these are differences that have not yet been staged for the commit. I can also look at which changes I have staged by saying git diff staged. I will say that it's created the hello file out of the line. I can also then do something like add another file and in there I can add bar and now I will say git status says new file bar, new file hello and hello is still being modified because there's a line in there that I haven't said I want to include and at this point I can create a commit by saying git commit that creates all of the changes that I've staged and creates a commit out of it creates a snapshot. It's then going to open an editor and it says please enter a commit message for this change so this is basically how do I describe this change to someone else who's looking at the list of changes that I've made or even just for my own records like why did I make this change I wanted to show if we'll say it that way. And so now it says great I created a commit on master this is sort of the first few characters of its hash this is the title of that commit two files were changed to the two inserted lines and it created these two files and if I now look at git status it now just says that hello has been modified because that difference is still there but the files that I added that has now been included with the commit similarly if I wanted to remove a file I could do git rm bar and that removes the file from the current directory and also stages the removal of that file so that if I make a commit that file will be removed in that commit right as if I now do git commit remove bar because it was unnecessary now I've created another commit right that's great so now we have a bunch of commits why are those helpful at all why do we want commits well it turns out you can do a lot of useful things with commit git log and git log shows me all the changes that I've made I could run git log one line if I wanted a slightly shorter summary which shows me the start of the revision hash the sort of unique name for each commit with the description of each one so this might be useful if I want to track what changes I've made in the past or if other people have made changes then I can see what changes they've made and why similarly I can even look at the exact patching that was made with the dash p flag which is the same as dash-patch which shows me what the change was in that commit so here for example you'll see that the commit 2244 where I removed bar because it was unnecessary removed this line from bar their bar removing the file this commit where I wanted to show Jose that I added the file bar with the content to say and added the line world to hello and here you can also see the other changes that I made earlier that we just have ignored and if I make more changes they will also be shown in this list I can also show a particular change so show shows you the commit that you named and remember master is just a name that points to a commit particular commit, master is the current commit on this branch so if I do git show master this is the last commit and you'll notice at the top here it says that head is pointing to master so remember head is the current commit so git show head gives me the exact same information they both just show me the latest commit on the current branch but in the log if I say copy this revision I can do git show that one and then it will show me what that commit was here similarly I can also use the dash-p flag to show what the actual contents of the change was to the patch and we can go back to a previous commit so git status there's nothing here I got rid of the one line that I added because it wasn't important now let's say that I look at the log and I want to basically I want to go back to what the repository looked like back here right back at this point before I wanted to show that I know git so I copy this hash the sort of name snapshot in my history and I say git check out that hash so git is telling me a lot of things now but if I do it less there are no files here because at that point in history the snapshot was that there were no files in that directory right so it's showing me the state of everything in this folder with that commit notice that it's telling me you are in detached head state what that means is pretty much there's no name that refers to where I currently am so if I make more commits from here no name is going to be pointing to those commits so I don't really have a good way of getting back to them I can't say like log master or whatever I have to remember the commit caches so it's telling me like you can make commits here but if you do they'll sort of just be out there floating in free space easy made to remember them why I can then also git check out master to go back to where I was I can in fact undo a change too so this remove bar actually let's make a new change hello is that food bar so now diff is food bar commit dash a so dash a means add all the changes that he files in order to him it's sort of the same as just add and git all the changes separately commit dash a just add to all the limits this is saying I want to include all changes in the current directory in this commit and I say add another line great so it made a new commit and now I decide that I didn't want food bar there after so then I can type git revert and the name of that commit which git told me here so I'm going to revert that change and what that's going to do is that git is going to look up the change that I made in that commit and do the inverse of it and apply it to the current head right so if I do if I show the gift the diff for this change or actually so it's going to take this diff right which said that I added a line to food bar it's going to turn every plus into a minus and every minus into a plus so every removed line is going to be an added line and every added line is going to be a removed line and then it's going to so if I do git revert this it's going to create a new commit that undoes the previous commit so you notice it dropped me directly into my editor with a message that has already been filled out saying revert to this commit with including the hash of the commit that I'm reverting and now if I look at the log you'll see that the added a line commit is still there in the history that is followed by a commit that reverts that change and now if I look at the contents below you'll notice that there's no food bar in there anymore because that change has been reverting I can also look at the changes that have been made over a period of time so let's say for example that I want to look at all the changes that have been made since this note commit well I can do git diff that dot dot so what that means so dot dot gives the commit range and if you have say A dot dot B what that means is select all the commits from A to B if you leave either of them off what that means is head so this here is the same as this and head as we remember is the current commit so what this will actually do is show me all the differences between what was in the repository at the time of this first commit and what is in the repository now and that is only that file but if I now added hello food bar committed that with a message add back food bar so notice that I can use the dash M flight to add a commit message without being dropped into my editor just a short hand way to save some time so now if I ask for the diff it will show me that hello has these lines both added right in fact I could also do so remember this is the change we reverted so we would expect that a diff from this point removed that line because that was the change that we reported later so indeed if I do this oh I added the same line didn't I the zoo was so if I now do get from that it will tell me that since that point in my history so since where we were when we were here the changes that have been made is that food bar has been turned to zoo bus if I went back to no the changes are that I just added those lines right because the comparison points are different in addition you'll notice that now I have a bunch of weird commits in this history and what if all of this like add back business like all of this is not really important the only thing that really mattered was that I wanted to show that I know so really all that matters to me is that the master points to this commit all the other stuff in between I can just get rid of I just want master to start pointing here well I can do that with git reset so git reset is saying take the current name the current branch which in this case is master and set it to point to this commit instead of whatever it's currently pointing to so if I do this now what it's telling me is if I look at the log we're now like master head is pointing to master master is pointing to this commit and these are the only commits I've seen so far because master now points to that commit believes that the current state of the world is this and therefore all of those other changes that I've made are now in depth they're on stage changes so it hasn't gotten rid of anything from my working directory at all it will generally not do that unless you unless you pass there's a command line called dash dash hard if you pass that it might change your current working directory but in general it will not so here when I did git reset it didn't like change the composite line files it just changed where the history git thinks I am and so any difference will be compared to that as opposed to where I previously was so now these are the changes yeah so let's say that I decide that I want to add hello I want to add the change from hello right so hello currently has a change which is add this line zubas hello then now this change has been staged to be included in the next commit so git diff will no longer show that change it only shows the deletion of bar in fact sure let's rmbar as well so now I'm about to make a commit that deletes bar and adds that line to hello let's say that I actually just wanted to remove bar I didn't want to make that change to hello git reset hello will unstage a change that I have staged so reset has two meanings it has change where the current branch points and remove this stage change it's kind of stupid that it's been overloaded to mean two things it just so happens to do so if I do git reset hello and git status it will now tell me that bar is staged to be deleted but the change to hello is still not staged so if I make a commit bar will be removed but that's the only change that will be included in the commit so clearly as we've sort of seen so far names are really important to me being able to name things whether that's through a branch whether that's through a head or using hashes directly there are a bunch of different ways of naming things and it turns out this is pretty handy sometimes you want to log say the last three commits or show the difference in the last two commits revert the previous there are a bunch of these kind of things that would be handy you don't have to go through the log all the time what copy paste or vision hashes and so git has a really handy way of talking about commits so for example I mentioned how you can make your own branch so I can do git branch b this creates a branch called b that points to the current commit so currently master whatever the current commit is the current commit is this hash so now both master and b point to that hash if I now make a commit here so if I do git show b it will show this commit if I do git show master it will show that same commit it shows that same commit so b and master are the same commit currently if I now make a change to master so I do bar sorry and I make a commit on master sorry then now if I git show master the latest commit on master is that commit the latest commit on b is still the one that master was pointing to because b is still pointing to the old commit so in the log you'll notice that b is pointing to this commit master is pointing to this commit because there's only the branch currently on that gets updated when you make a commit you can switch to another to an existing branch by doing git checkout and then the name of the branch b so you'll notice here if I now kept hello it still said if I now kept bar it still says so say if I check out master and kept bar it now includes that change so I can switch back and forth there's also a name called just dash so dash means go to the previous name I was at so in this case switches to b master the master is a convenient way if you're switching back and forth ignore tags tags are handy but they're basically read only branches or you make the ones and you can't change them they're just sort of think of something like you're making a version release like I want to release version 3.0 by software I would tag that commit with 3.0 that tag will never change it will never point to anything else so tag is like a write once read many times type of name there's also so we have this log let's say that I want to see the difference between b and master I can do that that way so this was dot dot to show the difference between commits I can also look at let's say that I want to look at the last change that happened on master if I do get the master that doesn't show me anything because what this is really saying is the difference between master and head I'm on master so head is master so this is the difference between master and master that's not particularly useful instead what I can do is I can add a carrot what that means is the commit before this one so this means the commit before master if I put anything it's dot dot head so this is saying the commit before master to head and head is master so the commit before master to master and that will indeed show me the latest commit I can go further back too but then I have to switch from then I can just add more of these so this is the change from the commit before the commit before master to head and similarly I can keep adding them if I use tilde which is the same as carrot then I can even do things like tilde3 which is go3 commits back or 5 commits back or 6 commits back so I can keep moving back as far as I want in general commits will operate on head unless you give another command so if I do getDiff what that really means is getDiff head similarly if I do getShow which is the current commit so it will show me the current commit so over time you might notice that we get to a point where let's go back to where we had a long weird history that was kind of useless down here so here I had a long ugly history so I'm going to make master make master point back to here give reset hard saying remove any local changes I have and just make to the current directly look like the current commit I have a slow file but I have a log that has a bunch of weird stuff in it that's much unnecessary changes that I don't really care about and it turns out that very often this ends up happening when you're doing development you'll have some commit that you wrote up very nicely where you like added a feature and then it turns out there was a typo in that feature and then it turns out you have to make another change in that feature and then you have to back out that previous change as you end up with this long list of commits that are getting shorter and shorter and shorter in your description because at the end you just type like the commit message is typo or x or fixed this very easily ends up happening but it's not really very useful when you come back to the same folder like a year later and want to figure out what change you made in y and so git provides you tools for basically editing your history for saying all of these changes I can really express in a better way there is first of all if I want to make a change I can do something like let's say that I made a typo somewhere let's say that in hello this shouldn't have said Zubas it should have said Zubaz Z because of course that was the typo clearly now I don't really want to make a new commit with this because the previous commit the one I'm currently on that's what changes from Vubar to Zubas so that commit maybe was sensible with the typo in this case I can do git command dash a so commit dash a is going to include all the current differences in the commit that I'm about to make and I can say dash dash amend which is instead of creating a new commit amend the current commit with this change so basically undo the current commit and then redo it but including this change so the current commit Zubas adds Zubas here if I wanted this difference that I made previously actually maybe it's easier to show this in a real here so this is the stuff for the hacker tools lecture so let's see I probably made a typo somewhere in version control so the last if I look at the log here it's like a bunch of stuff here and the last thing I did was add some version control exercises ok so let's look at this the bottom let's say that this should say repository right so the diff now is that that line change from saying repo to repository like I can do color verbs and it will show me just that difference but I don't really want to make a new commit just for this one change I sort of want to just include that with the previous change that I made if I do get commit dash a dash dash amend what that's going to do is it's going to change the previous commit to also include this change it's as if there was no commit that introduced the word repo and so there was only the commit that introduced the full word repository in fact I can go even further than that by rewriting entire segments of history this command, get rebase lets you take some segment of commits undo all of them and redo them in a different way dash i is a interactive like ask me what to do with every step and I'm saying do that for all the commits from six commits previous to ahead to ahead or just this way it's the same way so the past six commits we're going to rebase so this is the history of the last six commits to the current branch and then asks me what I want to do about each one and you'll notice that the bottom here it gives me a bunch of options so pick is the default pick means leave this commit the way it is don't do anything weird with it just leave it the way it was but I have a couple of options I can say R or reword what that will do is it will reapply that commit where it was in the history but let me edit the commit message I can also do edit which is when you get to this commit when you're like replaying this commit then stop before continuing and let me make edits I can also say fix up so fix up is saying fold this commit into the previous one it's basically pretend that when I made this commit I pass dash dash and then I'm just going to get rid of this commit this commit is no longer going to be in the version history there's just going to be this commit which is also going to include the changes from this I can also say squash which is a little bit like fix up except that it keeps the commit messages from both but there's still a thing that won't be committed at the end I can also reorder things so now so for example here I have added a line and revert added a line I don't really need those two commits those are sort of unnecessary because they cancel each other out so I can just remove both of them now when it's replaying the history it will just never apply those changes it will be as though they never existed similarly this add back foobar so let's see this adding y was a fix up this we're going to reword into added suba z right and maybe this line who knows show what edit does so now the new edit history is going to be this commit then this commit after we make some edits then this commit with a change commit message and then this commit is going to be folded into that when I exit this rebase is going to start doing that it says okay I started doing it I stopped at this commit this is the one we said we wanted to edit and then it says you can amend this commit now so I can change it if I want to so here let's say I actually meant to also echo world commit to edit that commit I'm currently at the rebasing and then I'm going to continue rebasing here I asked it to be able to change the commit message so it's telling me here you can edit the commit message and now if I look at the log notice that the log looks a lot cleaner now there's none of this like added and reverted that has gone away this remove bar because it was unnecessarily still there this commit now adds back now adds back Zuba Z so I edited the word and there's no commit following it so I've basically rewritten my history into one that's easier to grasp later right if I wanted to I could rebase all of this commits into a single one that's often a little squashing it's like saying all the details of what I did in between here don't really matter all that matters is the overall change so very often if you make a contribution to some open source project you may want to clean up your history because the fact that you like introduce the bug and then fix the bug is probably not relevant to those maintainers when they're trying to figure out what change you made instead you're going to squash your commits or into some smaller logical commits before you send it to them so they can review the commits individually so a common use case for version control is to allow other people to also make changes to the same things that you're working on right so for example for the lecture notes for this class Anish Kosey and I are all working on the same repository and in order to let you do that Git has the notion of remotes a remote is basically a copy of the same git repository that lives somewhere else it has all the same commit tashes it has all the same names potentially in general it's just you tell Git the existing copy of this somewhere else so for example if I do git remote v you'll see that I have a remote called origin so origin is the default remote name that points to this URL which you'll notice is a git hub URL that's because we happen to have a copy of the repository on git hub and what that means is that I can do say branch that lists all of my branches but I can also do git branch dash a which shows me branches that exist elsewhere basically names that exist elsewhere so you'll notice that under the remote origin there is also a name called master so you'll see that origin head points to origin master and origin master is a thing that rep parser shows me which commit something is pointing to so remotes origin master so that is pointed to that commit similarly if I look at my master that is pointing to the same commit so currently the latest commit on the repository is the same as the latest commit on master in my repository if say Anish made some changes and pushed them to that repository what a push does so you may have seen the command git push what git push does is really this it's saying push to the remote origin and change the name master there to point to whatever the current commit is so it's basically this and what this mapping does is it will set remotes origin master to point to head that's what a push does so it means that it sends all the commit I have locally sends them to github so they're available for other people to download and then it changes the head the name master on github to point to the latest commit on github and so it's really just another set of names that just happen to live on someone else's computer similarly you may have seen git pull so what git pull does is it first does a git fetch origin git fetch is just give me the get me what the latest what all the remote branches at this origin or at this remote give me what commit they point to so if I run git fetch origin notice nothing happens that's because there are no commits there are no changes on origin that I have not seen if someone were to make a change on origin so if someone were to push their change to github fetch would say the remote name master now points to this commit right so if I then did this git rev parse to the master at origin I would get a different commit hash than the one I have specifically if Anish made some commit on his computer that would get some name foo and he would set his master to point to foo and then it would set the master name on github to point to foo and when I get fetch origin it's going to tell me remote's origin master now points to foo and then I have to choose how to fold those changes into my master right so my master currently points to this commit whereas if the master that's on github pointed to a different commit I have to find a way to reckon something of course what I could do is just reset my master to point to whatever this is right so I could set my master to just point to whatever commit is on github if I wanted to but of course that means that if I have some commits that I have made locally then those would just be lost right because they have changed my master to point to something else so you can see a similar example of this is let's say that here I made this repo change so I make a branch called edit1 and then on so that points to the current commit then I make a commit on master saying fix typo then I check out edit1 and I change my job so now there's one commit on the edit1 branch there's one commit on master and they're different the two branches are diverging and so if I now look at master I'll see that the latest commit is this one if I look at edit1 I'll see that the latest commit is this one and they're different so the question is let's say that I now wanted to bring the changes from edit1 into my master you can think of this as just the same as trying to do a poll there's some name elsewhere but it's off into my current branch and the way you do that is using the merge tool so git merge is saying take all the changes from this other name compared to where they diverged so you can look at this like this so this git k is just a handy way to can I now zoom here that's fine I don't know if you can see this this point is where master and edit1 diverged as you can see from the graph so this is the shared commit they both branched from this has one change and this is another change what git merge will do if I'm into master and say git merge edit1 is it will look for the shared common ancestor take all the changes from that ancestor to the other branch and try to apply those to my branch or, shown in comments the dip from this is the shared commit right because I only made one commit on master to edit1 it will take that difference and apply it to my current branch and then it will create a commit on my current branch that includes all those changes so if I now have you git merge git merge edit1 it creates a new commit for me the message is merge branch edit1 and you'll see that the merge made that change to read me that I made on edit1 so now if I look at the log the logs are I fix the typo and then I merge the branch and notice that the history of edit1 has also been merged into my history but now this history isn't really linear anymore this is branching and forking so it splits at some point and then you merge it back together whenever you create a merge commit and that merge commit basically says that my previous commit is actually two commits it is this commit from master and this commit from edit1 and this would be the same if someone made a change on git hub then I would git fetch origin and then I would git merge with this origin master here it's telling me already up to date because there are no changes on git hub that I have made locally that would create a new local commit for me that includes all the changes that have been made and if I then do git push what that would mean is the merge that I made so all the changes I have plus all the remote changes are going to be bundled up into one commit and then the remote master the name on git hub that's then going to include all of the changes that have been made in between git pull you may have seen is really just a shortcut for git fetch origin and git merge master they're really just doing the same operation there are other ways to merge changes too like you can pull and then do a rebase so for example let's say that a niche made a change to some file instead of me creating a single commit that has all of his changes and all of mine I could just sort of undo, rewind all of my changes apply his changes and then try to apply my changes on top of that again it's basically as if all of his commits were like spliced in before mine so if he adds a line at a line it will be as he added a line first and then I added a line sometimes though imagine that we both made changes to the same file two commits that you're trying to merge and they both try to change the same thing then you end up with what's known as a merge conflict so a merge conflict basically tells you that git doesn't know how to reconcile these if we go back to our edit example if I make a change to version control where I change try to fold because why not I'm going to do it quickly and on that other thing I change try to be food if I now go back to master and try to merge with edit 1 it's telling me that it couldn't merge these changes specifically there's a conflict in version control and automatic merge fail if I look at this file now it's going to give me this kind of information it's telling me that this line on head so on my current branch looks like this but on the other branch looks like this it doesn't know how to reconcile those changes it's telling me I have to choose what this segment of my file should look like and so here I might say that oh I want it to actually say on a repository food once I've made that change so now there are no other changes in this file now I can add that file and then say now commit that result that's what I want the end result of merging these two to look like and now if I look at the log it now has a merge commit that includes the x from the edit 1 branch and the x that I made on master so it's now reconciled those changes when you're running to merge conflict sometimes you can just open it with the editor you can also use get merge tool which will open about three way view of all the changes and let you like select between them I'm gonna not talk about force pushes because we don't have time ok so I think that's sort of the overview I wanted to give you you probably get the sense that there's a lot of stuff going on with git and this is why people think that it's sort of black magic because there are so many commands that do so many weird things and you end up in weird corner cases where it's telling you that there are merge conflicts and you don't quite know what to do and there are a lot of good tutorials that I linked through in the lecture notes as well that take you through basically interactive tutorials on how would you deal with this situation what commands would you do and chose you the commit graph and how different commits are associated with one another the basic thing I hope you take away from this is that git lets you keep track of changes over time including from multiple users recognize whenever changes would take place and overlap and lets you resolve those without losing any changes and as you look back at changes you made in the past and basically keep a record for your own and for other people's sake about what changed and why hopefully this notion of sort of names and hashes is a good way to think about that because that is the way it manages things internally and thinking about names and hashes as completely independent entities in git is really really helpful because if you try to basically any other model it's going to be wrong and so you're going to run some command and not understand what it does because you have them mixed up in your heads this is partially because in other version control systems there's a much closer association between say branches and commits like in subversion or cds which are other somewhat older version control tools you basically couldn't play these tricks like rebasing the names and the commits were tied so closely together it's a lot of content in very little time I hope some of it was useful check out the lecture notes they have a bunch more details about that we didn't have time to go through about how these commands work I also recommend you look at the further reading links because they have some of these interactive tutorials and hopefully some of the exercises should be in slightly more expanded shape by the time you get to look at them are there any questions? I know that was a lot of the points alright well I guess we'll see you on Thursday