DevOps Master Class - Part 2 - Master Git!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone welcome to the next part in our devops master class and this is mastering git i really think this is a core capability everybody needs no matter what you do the ability to version control the work you're using really is critical as always if this is useful i really do appreciate a like comment and share and hit that bell icon so what i want to do in this is really go over the basics and really the building blocks of gear i actually want to talk about how git works under the covers which i don't always go into those types of details but i think forget once you actually understand what it is and what it's doing it makes a lot of the concepts actually a lot easier to understand then we'll talk about actually using git and then some more advanced concepts don't forget all of the source code i'm using is in the repo for this class it's linked in the description below and make sure this video again is part the playlist and that repo there's the whiteboard the powerpoint that i'm using so firstly why do we even bother about aversion control system now notice i'm saying version control you'll hear it called a source control system as well but maybe we're not dealing with source files these are not dot c files for example it's maybe some artifact that i still want to work on collaborate with others and have different versions of now even as a team of one if it's just me i might have multiple versions of the same file and without some kind of source control system we get into this really really ugly place i know me personally for example before version control i'd kind of i'd call them names if we actually go and have a look so let's jump over to here for a second and if i go and look we've kind of without source control you can see these files i have over here on the left so i might have hey i've got my initial important file well then i create a important file v2 well i added syncs then i create a v3 with a feature well then i create my final version as i oh wait it wasn't final there's a new final maybe i use subfolders whatever that might be i end up doing kind of version control in a really really ugly way so version control system will help us because it gives us the capabilities to track the different versions it lets us have metadata hey i can put a comment in what was the change i can track who did it when they did it i could give it a certain label a tag it really helps me track all of the things related to that file so version control system is useful even if it's just me when you start expanding to more than just you it becomes a necessity if i'm working as part of a team i really need a way to collaborate with the other people in a consistent manner to help us bring together data now one thing i will stress from the start when we start talking about git for example is just using the file system if that file system is stored on something like my one drive and i have a local copy well that one drive syncs up to the cloud and syncs to other machines for me on my own that's probably fine when i start working with other people well i probably need a different way to kind of share that version control system so what are some of the benefits the features i expect from a version control system it's going to be the source of truth i don't want everyone having their own copy of a file saying they know mine is the right one this is the one you should be leveraging by having a version control system it becomes a single point of truth for the intellectual property of my project or for my entire organization it enables collaboration see if i think about the idea that hey i have different people working on a solution maybe some people are working on a bug fix some people working on a feature some people working on a new major version i need a way to kind of bring all that back together and track it they need to be able to see hey the changes that other people have done but in a very controlled way if there's a problem i need to be able to roll back if a customer has an issue well what version are they using so what version of the artifacts the source code do they have so this is a key thing that enables actually collaboration enables devops all those things we're going to talk about with features like branches that i'm going to talk about it enables us to have those different tracks of kind of work going on it encourages consistency it encourages a certain way to work but obviously i still need good process so always talk about remember that the people process the tools involved whatever you pick is going to be a tool and then we need to use it in the right way so it's a good process we need to agree as an organization this is the approach this is how we're going to use branches for example and this is when we're going to check in we're going to do this daily this is going to then trigger some continuous integration to test to make sure we're not introducing problems but it will encourage a level of consistency but we still need people to follow a process it's going to give us that full history and immutability so what that kind of means here is in my version control system it's going to have the ability to go back and see who did something what they did and why they did it we have that metadata remember so it's going to give me that great ability to go back and track and see exactly what changed it is a strongly version solution and it's immutable in that as we'll see i can't go back and mess with history outside of the actual features that are included i can't go and hack a file from the past and change it to something else it will break it will tell hey something's gone here this doesn't match anymore so it gives me an immutability in terms of hey i get this very strict view of the past i want to change the past i have to use the tooling but it will be very visible that i've actually do that and it hooks into additional security mechanisms so if i'm bringing all of my artifacts my source code whatever into some central repository i can hook into other things for example let's say i'll put it in github github has these capabilities that would go and say hey look you have a secret um you have an access signature in here you probably didn't mean to do that i'm gonna flag this and you can go and do something about it and there are other types of security i can hook him again we talk about shifting left security earlier and earlier not hey it's in production now let's do a security scan hey as we're checking the things in what can we be doing then to find any security vulnerabilities hey as we're building hey we have these dependencies we should go and fix that constantly checking those things and it gives us this ability to hook into continuous integration continuous delivery by having our code constantly checked in that is what lets us then have things like continuous integration it will trigger maybe nightly maybe every time i do a commit every time i do a pull request we're going to talk about all these terms that enables me to get that integration now there are really two types of version control system centralized so if i think about centralized this is not hugely used this used to be how it was done and when i used to work at logica we had a centralized source control system and i can really think about in a centralized world as the name suggests there is some central repository and that has all of the different artifacts all of the different codes that i might have and then what happens is hey look if i want to work on a certain project i check out certain files now they are now locked i now essentially have a lock on that and then someone else comes along okay they want to work on that file so they check out that file and only they can work on that one and what the challenge becomes is well now someone else comes along and they want to work on that file they can't because i've got it checked out they may be able to get a read only version that's really the best that they will be able to do so the the challenge we get with this is kind of this whole locking and kind of locking people out to be able to do things and it's also i only have the files locally let's say this is file four and five i only have those on my machine they only have file two if i was offline if i was on a plane and i wanted to do some work i don't have files one or three or four or five on this machine so there's kind of a challenge around there so it can really kind of stop me being able to do work that i want to do because i kind of only have certain files the next one we have is distributed now we might still have a central copy of the repository but now the point is everyone who is participating has a copy as well so that's centralized if i think about distributed so sure in the distributed i still have this idea of a copy that's available to all the different people but now this person on their machine they actually have the full copy they have a full copy and they can kind of synchronize they can pull down changes and push up changes likewise this other person they also have a complete copy of the entire repo when you first see that that may seem kind of scary because i'm all changing the same folds at the same time this is where we have things like branches this is where we have things like continuous integration we want to check in daily so we find early if there are problems if we are having some clash and we resolve it so often we see this as kind of this idea of this kind of remote origin where all the different people will go and sync their changes up to and this is what we're focusing on this is git and when you hear about things like github and azure devops well they are using this methodology so github azure devops bitbucket you kind of name it they're all based on git and what that means is my local tool set is just git and then they are just kind of a remote origin that i can use for my repository now they might add additional capabilities additional features but fundamentally it is this and once again the key point here is we kind of can synchronize through kind of pull hey tell me the changes and push mechanisms now one of the things that obviously you'll see about this is well what about conflicts then because i can absolutely be changing all of the same files as someone else this is why we want to kind of do this integrate often that is a key point i am not going to make changes for three months and then try and merge it back into the same copy everyone else has yes there'll be a whole bunch of conflicts there'll be challenges this tooling gives us the ability to handle those things but as long as we integrate in often we'll find those we can resolve them okay one other thing you might be looking at this going that could be a lot of data potentially if it's a really big repo but most machines today are not struggling with disk space this space today is by and large pretty cheap and so it's not a huge problem to have this idea of hey i'll have a full copy and i think the benefit if i'm on a plane i can operate on anything i want we just need good processes around it so obviously git is the focus for what we're talking about this is a free open source distributed version control system now free as in git is free things like github and azure devops if i choose to use those depending on what parts i use and what levels of service there might be charges for them but git itself is a free open source project it was basically just using your files and folders on the file system we're actually going to spend a bit of time looking at that at the start we want to understand how git actually works under the covers so you can really not be afraid of it we can understand what it's doing it's like okay i get what it is makes sense i now understand what the commands do when i execute them so there's no process running there's no service on my local machine i'm using a command and that just manipulates things on the file system obviously this is what we're going to focus on now interesting it was actually created by linus yep the guy who created linux he went and created his own version control system for this and as i mentioned i mean this has really become the de facto standard if you look at pretty much all of the solutions today including github azure devops repos bitbucket they are using git so it really has become that standard solution you'll hear me say repo repo is a repository kind of use those interchangeably nearly all of this is going to be demo so go and get get if you go to this website dash scm so on here you can actually see there's downloads and for downloads it's mac os windows linux and there's sort of a download for windows if i go to linux for example it might say hey you can do apt-get install git so there's different ways to do it but what i'm basically getting here is git installed on my machine so that's the kind of the key first point now once you've actually installed git it should add it to my default path so if i'm over here if i open up sysdm this is obviously windows linux has its own thing but if i go to advanced environment variables and if i look at my system path and edit we can see here it added c program files git cmd so that's why it has kind of the get executable that's the thing we're constantly going to hook into so i want that in my path so i can really just type git from anywhere now the other thing i really would recommend is vs code now for vs code that's kind of linked in the main repository for this course and i've got kind of the downloads for that but what you're going to do is once i have vs code if i actually go and look at my settings there's kind of one setting you need to do and the big one here is the git dot path so you're just going to tell it where is the get executable once i do that it really lights up vs code to now have all of its source control capabilities so actually now i'm not going to use the vs codes special features until right at the end i'll show it to you i'm just going to use the command line but you see this little icon over here well this gives me access to a whole bunch of integrated source control it will go and track the changes there are extensions a really good extension is git lens here which actually adds even more great features around version control i can see kind of all the the commits that are going on i can see branches that are happening as i'm editing my code and you're going to see this as we kind of go through if i just click on a line it has this kind of blame line you can see it's old me i made this change that is the git lens integrating with the version control and showing me that so i do recommend using vs code i do recommend installing git lens it's just going to make these things so much nicer so that really is kind of a key thing we really want to be doing so go and get git nearly everything we do is going to be on a local machine i don't need to go and buy subscriptions even when i do a demo of a remote solution it's still not doing anything you have to pay for everything we're going to do today i can do for zero pennies so let's actually think about this for a second and just really quickly if i think about well actually just creating a repo now it's going to be empty but you'll have a repository so if we jump back over for a second over here now this file this script dot ps1 it's in the part 2 master git folder of our devops repository and i'm actually gonna use this for pretty much everything we do so you have a full copy of everything i'm gonna do now firstly i can check what version if i do get dash dash version i can see down here on the bottom i'm running the [Music] 2.32.0 windows now any folder can be turned into a repository so if i just go to cd dollar scratch for a second and i can just make a directory make directory git play one and then just move into that folder now that folder right now is completely empty if i was to actually move over to that and i've got kind of view hidden folders turned on you can see it is completely empty there's nothing in it if i was to type git init it's now turned it into a repository and it's even telling you hey look we initialized an empty repository in a sub-folder called dot git and that is the key point of this and you can see it it's there so now i've got this git subfolder and it's created a bunch of different folders now we're going to go into actually what these are later on but that really is just a key point for this now at this point i could absolutely go and clone for example here i could clone the devops masterclass actually into this folder i could clone a local folder but i'm not really going to dive into all of these things right now we're going to go into this in a lot more detail later on but essentially i now have a completely empty repository if i do my get status well there's no branch yet nothing going on if i just delete that folder and now do it get status again it's not repository that's it that is what git fundamentally is it's all contained in that dot get subfolder so that gives you kind of an idea that's how easy it is and then obviously i need to start going and actually adding things into that repository but that's it that that was creating a repo get space in it obviously you want to do things a bit more interesting than that but before we start doing things a bit more interesting there is some initial configuration i talked about the idea of metadata kind of who did the things and so before we go any further there's a few basic configurations we actually want to perform and so let's actually go and do those and actually see get in action so that was it for the powerpoint so if we jump over i can think really that the first things i'm kind of going to be doing is i think about well who am i so there is a set of global let's just clear the screen for a second there are a set of global configurations there's this git config-global dash dash list so if i actually execute that we can see i've already populated over here my username and my user email so these are global these will apply to any repository i create on this machine now to actually set those i just do get config global user.name and user.email now i could absolutely create dash dash local versions so if i wanted different values for a different repo i could do get config dash local user.name and use something else there's a whole bunch of other configuration items i can do a get config dash list dash show origin and i can see hey where are all these different things actually coming from for my various configurations so i can see all these different options over here and there's a whole bunch of them so i just keep kind of pushing enter through these so i can see okay there's some from okay there's user dot name john savile my default branch and that's actually now my options and queue to exit out of that the other setting you've seen me kind of configure here is this init default branch and i'm calling it main so obviously there's been a lot of changes socially in the world and its default name used to be master there is a move to change that to main so what we can see is i've changed mine here to now be called default branch name is main so it's really kind of a key point about all of this so now when i create a repo it has to have a default branch this is where my code just lives by default and so mine is going to be main and that's again over time that's going to become the standard anyway so let's actually dive into this for a second let's really think about what is going on in this environment now in get as i kind of mentioned already it's just things on disk there's no magic going on everything is on disk so i can really think about what i'm going to have is a whole set of blob files so i just have these kind of blobs blob one i create another file i get a blob two i'm gonna talk about how it stores these in a second but every single object ends up being a blob it is actually a z-lib compressed file which again i'm going to i'll draw that out and what happens is for every single one of these it generates a hash now it's a sha-1 hash value which basically based on the content is guaranteed to make it unique but also if i had the same content in the same files it would have the same hash value so it would only actually get stored once the file name is not part of this the files are called the hash values and we're going to see this in a second i'm going to walk through this actual structure now by using this sha1 for the name it guarantees the name would be unique it also guarantees i can't change the contents of the file if i change the contents of the file it constantly revalidates this sha1 hash every time it interacts with it so if i went into the dot git folder and the objects and started messing around with content well the next command i run that used that it would say this doesn't it's not integral i've lost my integrity so i know someone has messed with it so i can't just go and play around with things that shaw one hash is going to generate is constantly being validated at every single interaction so it's just going to create those on the file this is used throughout all of the structures now when i actually create something called kind of a commit there's no file names on these blobs so what it actually does is there's another type of object called a tree and a tree actually has file names so you might be like hey file1 dot txt and it uses a pointer to the actual blob on disk that represents file1 and hey i have dot file2.txt and that points to the blob again if they had the same content they would point to the same blob and once again the tree is a hash value name so once again i can't go and mess with oh okay i'm changing this to fold two now points to a different blob when it gets checked that would no longer match so i'm constantly guaranteed that no one is messing around with these hash values it is an integrity feature so the tree points to objects on the disk and tells me which file name it actually represents and then what we have is a commit so i can think about a commit is a certain point in time snapshot of the entire repository so this is a key point when i do a commit in get it is the entire contents of the repo if i've changed one tiny file it is a complete snapshot of the entire repository every single time i do a commit but remember how do we store things we store them as the these sha-1 hashes as blobs so if only one file changed and nothing else had i'm not restoring everything again these have not changed the tree would just point to the existing blobs i'm not really wasting a whole amount of things so when i do that a commit that point in time well what it actually does is that commit points to a certain tree that represents the state of the files that are in that point in time then it has some metadata it has a whole bunch of things like author creator date etc etc and then it actually links to a parent now if it's the first commit it won't have a parent if i already have things and then i do another commit well there's another commit object up here and it would point to its parent this commit is also a sha-1 hash for its name so i can't mess with this either so a sha1 hash points to a sha1 hash which points to sha-1 hashes i can't mess with anything in the history it points to the shah one hash of the parent why i can't mess with any of these things all of these things essentially are used to check the integrity not certainly security but it helps ensure the integrity of everything i doing i know nothing really could have messed with this because of the shah one hashtag everything we've done so far is a shah 1 hash so it's really helping make sure the integrity of this is rock solid and this is fundamentally get everything else we do is based on this concept everything is an object on the file system and that really is the key point when we talk about branches a branch is nothing more than a pointer to a certain commit that's really all that's happening we're going to walk through all of these different things so they're the objects let's actually see this in action so remember what happened we did get in it now when we did get in it remember what did it do well it created a dot git subfolder now what it actually created under there was a whole bunch of different things but one of them was an objects folder which currently is going to be empty but it's going to store all of the different things actually under that objects now there are some other structures as well which we're going to talk about in a little bit but let's start actually populating this so let's jump over and we'll start with okay so we already did our git init so we did our git init command but remember we deleted the folder so i'm going to run git init again so now it's created that dot git folder so if i look at my dot get i can look at my objects and there's just an info and a pack folder but it's basically empty at this point because my repository is empty there's no objects to actually store so let's actually give it something that i want to store so i'm going to create a file i'm going to create a file called test file and i'm just going to say this is a quick test and save it now remember i'm saving this to my current directory which is kind of that parent folder to the dot get now i'm going to actually run dot git add now what i'm going to do is quickly shrink this over a little bit so i want you to be able to see at the same time kind of what is happening over here let's just organize that okay so right now they're the folders what we're going to do super quick is i'm going to run git add dot now what get a dot does is basically say hey add everything that's not currently being tracked or that's changed if i do get add dot keep it on this right hand folder now it's created a folder called 43 and inside there there's this just 38 character name so that's kind of weird so what has it done so at this point the way it works is this objects folder contains all of the blobs so i can think about in the objects it has all of the blobs all of these sha-1 hashes are 40 characters now what it actually does is it organizes those into subfolders so it creates a whole bunch of subfolders that are the first two characters of that 40 character shell value so in the next one it'll create a different two first characters and then what it does inside those is it puts the blob then it has a 38 character blob actually blobs of the right word i'm not going to say blob here we'll just say object because other things kind of get put in these as well and that kind of repeats around so what is this this two character why bother well essentially this is just sharding sharding is where i distribute data in some way so it's distributing the hashes instead of having every hash in one giant folder hey we're going to break it up a little bit we'll take the first two characters make that subfolder send every hash that has the same first two characters is in one subfolder etc etc so it's a way to actually go and separate out the actual content so then there'd be another 38 character object that shared the first two characters so in total it's a 40 character name first two characters of the folder next 38 the actual name of the object so that's what it did it created that object that represents the content of that actual file so it's sharding out the objects okay so that that makes sense that's how it's actually storing it on the disk so if we jump back over that's not a commit yet though so what we want to do now let me kind of open up that files again if we look at get status what we can see is hey look i've got a new file that has not yet been committed this test file too so so far all we've done is create that blob i can even look at the difference between staged and commit git diff dash dash cached and now i can see there's my file my content over there what i'm going to do now is commit it so by doing a commit what do we think a commit is going to do remember a commit points to a tree which points to the blob this is going to create two objects it's going to create the tree and it's going to create the commit so i'm expecting to see unless by some huge coincidence they have the same first two characters two new subfolders actually created so let's do my first commit and right we see two new well zero zero that's a pretty big good sense we see zero zero and a5 actually created so what it has now actually gone ahead and done is it's created a tree object and it's created a commit object both of them just sha-1 files that have got written somewhere based on the name so some of these are blobs some of these are trees and remember all of these are actually just stored as these kind of z-lib compressed files which means i can't just type them out it says z-lip so it's trying to do this compression to actually help me with what we're doing so it's going ahead and this is how it's storing the actual content how do we know that well we can actually go and look at it so what it has given me over here so i'm not going to worry anymore about that file system and kind of see those get created so it told me something it actually told me hey look a commit a587842 so i would expect to see an a5 actual subfolder so there it is one of the subfolders is called a5 the first two characters and then the rest of the characters eight seven yep eight seven eight four two so let's see it's gone ahead and created the object we can actually look at those now i can look at the full commit by doing git log and it's actually showing me that full commit id a587 that huge character which is obviously the same as the subfolder and then that name i can see the author and the date and my commit message so there's that metadata now using get space cat dash file i can actually look at the type of what this is now i don't have to type out the whole 40 characters what we can actually do is we have to type enough characters so that it's unique so in this case i don't have many i could probably just copy the first five or i'll say seven it just has to be unique so i could say get cat file i want to know what the type is the first whatever number seven characters of the commit and it's telling me it is a commit i can actually look at it instead of doing dash t for type i can say actually look show me the content so interesting so yes it's pointing to the 40 character hash of a tree and it's sending me the offer and the committer there's no parent because this is the first ever commit and then it has my metadata comment so let's have a look at the tree so again we'll just take the first number of characters notice no it's 0 0 6 e which represents that 0 0 folder the next 38 characters so let's look at this one it says look at the type of this so what do we expect this to be well we expect this to be a tree which it is and then we can look at the content there's our file name so notice it's pointing to the blob which is the content and this is where it says hey this is test file.txt that's where we start linking the things together and then finally i could just actually go and look at the blob itself and once again i could do the type and it's just going to tell me it's a blob i can look at the content and there's my message so we can see all those things just kind of linking together there showing me hey the commit which links to the type sorry to the tree which links to the various blobs now let's prove a point i have a file remember my test file i'm going to copy it to be test file 2. so now i have two files that's exactly the same content let's do an add okay i look at my status there's a file i've not committed let's do a new commit now when we do a new commit well actually before we do the commit did we get a new subfolder no we still have three why didn't we get a new one test file two has the same content as test file one it goes and generates the shard one hash and says i have this already there's nothing to store but when i do my commit it has to create a new tree and a new commit object so if i run this now we have five so we have something new for the commit and something new for the tree and it shows us that it's like okay well here's our new commit id so this time we'll just speed this up a little bit look at the type again let's just look at it now notice also what we have this time it points to a different tree but it also now has a parent because it's the second commit it has a parent so we get a chain so we can actually see the tracking that's how all the tracking works there's no mystical other file going on in any of these things the way we get this change history is the commit points to its parent and we can then follow the chain up there's not some other special thing that shows me what's going on this is the key this gives us the chain and because of all these sha-1 hashes i can't just go and change something behind the scenes because the sha-1 hash wouldn't match it's that integrity feature so now we've actually done another commit so we've got some new objects let's just finish this and prove that point so that was the commit if i now look at the tree again remember just enough characters so that it's unique what we're expecting to see is two different file names pointing to the same blob which is exactly what we have same content same blob so it's being very efficient with actually how we're storing the space within there now i'm going to create something now as a nicer way to look at things so this is this get log one line graph decorate all so what it does it gives me kind of a log of everything that's happening it draws it as a graphical representation it does it these pretty one line abbreviated comments shows me heads and pointers and it shows me all the commits in the history of any branch so i'm going to use this over and over again if i run it now you can see this nice kind of history saying hey yeah i had this initial commit and then we had this second commit and this head main is pointing to that head main is that second commit so let's just for a really quick second talk about well what is that kind of thing that i'm talking about what is this head main thing that i'm leveraging so i'm obviously working on something how does it know which commit i'm working on so in addition to these objects the whole set remember these two characters there's also a kind of references folder and under this we have a number of heads and under here for me there's a file main i have one of these for each of my branches but then how does it know which branch i'm working on well what we also have under here is a file called head and the way it works is my head will point to a certain reference i either branch i'm going to talk a lot more about this later on in this case it's called main that's my default branch and this points to the hash of a certain commit that's all any of this is when i start talking about branches a branch is just a reference to a certain commit id how does it know what i'm working on well i have a pointer to a particular reference which just points to that commit id and we can see these so if we jump back over again and this is kind of a real key thing to understand because everything else gets honestly pretty clear so we go back to our kind of file system view for a second so firstly i can go to my references and we can see here we've got our heads and there's main if i open that with code it's just a hash and what is that hash hey look it's the hash of my last commit that's all it is nothing special it's just that and you don't worry about security what can i hack i'm not changing any code i'm just changing what does on my machine this file point to so that's main and then if i look i have this head if i look at what is my head file i'm pointing to a certain reference so that's how i know what i'm working on i'm working on the branch that my head is referencing and the branch is nothing more than pointing to a particular commit id that is it there's really nothing else going on there's no mystical things happening behind the scenes that's how all of this is functioning if we understand that everything else we're going to do with git actually is not that complicated so we think about git is storing objects as 40 character sha hashes it just shards them over two character subfolders we have a tree which assigns kind of the names to actually which blob represents that file at that moment in time because the commit references a tree commits form a chain by referencing the parent they're all sha-1 hashes they're all immutable the commit is a complete copy of the entire repository every single time everything but again i'm not wasting space the blobs only get stored if there's a change when i add them to kind of that staging the commits have that metadata and our branch is nothing more than a pointer to a commit what am i working on is pointed to by head so that's how it works underneath that's it nothing else we do is any more complicated than that now it's just using those things to actually do stuff so let's actually now use it let's do a few more interesting things we always eat stage things and we already committed things we've already done that in our plan let's really dive in and understand even more well what did we actually do we did this weird ad thing then we did a commit thing what were those things actually doing there's actually really three spaces we think about when i'm dealing with git i can think about there is the repository so i can actually think about okay we have the repo itself and this kind of includes the full history i can go and see all that everything under the get folder all of this is the repository that's fundamentally what we're doing here so there's nothing else there's no other registry or daemon that is the repo everything installed on this dot get if i delete the get folder i've wiped it all away this is what enables us to collaborate we might replicate this to somewhere else that other people can then go and fetch now then also i as kind of the human being i want to be able to work somewhere i don't work well with blobs and stuff like that so i have this working directory so i have this working directory that i see as the file system so this to me would be kind of the parent to the git folder i actually see kind of file dot txt so that's my working directory where i can interact and i can do things now the challenge is i might be working on a whole bunch of things i don't want all of those things to go into the next commit i want to be able to stage specific things so in between these two we have the idea of stage also called index and that's where i can go and put things to say hey my next commit this is what i want you to take so i can add things to staging that i want to put into my next commit it helps me organize so i can have some things and not other things when we stage them i we do the add that is when they get that blob created so i can really think about okay to move to here that is the whole get add and then kind of file or files or dot to get to staging to the repo that's where i do kind of the get commit and then m and some comment that moves it from staging to the repo so let's kind of see that again so remember now what i'm going to do super quickly is i'm going to create a function called get graph now remember that get log command i showed one line graph decorate i'm just going to create a function for that it means i can just run git graph in future and it does this nice single view of the commit so i'm going to use that over and over again now if you wanted to you could add this to your profile and i've got some other commands here so you could set the initial branch name actually when you create your new reaper when you do the git in it but once again just to confirm those different steps so i could edit the file this is a quick test line two and i can save that now from here i can add test file so what that does is it stages it so by doing the get add if i look at get status you have changes to be committed so what i have at this point is by doing the git add i've staged it i said look when i do my next commit these are the things i want included in the actual commit and then my next thing i'm going to do is actually now i could add other files i could carry on staging more and more things then when i'm ready when i've got staging complete and i want to perform that commit well now i would actually go in and at this point i could say okay oh let's create the third file just to show you the differences if i do a get status now i've got kind of a file that's untracked and a file that's waiting to be committed so if i add to a get commit dash m and do i get status i've just got one file that's currently waiting to be committed if i do my get graph command if i type it correctly you can see hey i've moved up my main branch has moved up a commit and that's where my head is pointing to i do my get status again i just got this one untracked file i can actually look at all of the details if i do a get log dash p it will actually show me the differences between the various files so i can see all the different things that changed see all my commits i can really see everything that's going on i can see all the different detail i can even look at the differences between specific commits so there's a git diff commit commit so dot dot commit so if i do my get graph again and what i could do at this point is i could say hey get def so let's say the difference between this commit id this first one dot dot the commit id of this one and it's showing the differences between my first and kind of my last commit so i have that information so what that is doing remember is if i looked over here remember i have kind of multiple commits well if i use this kind of git diff hash dot dot hash i can tell it hey show me the differences between the commit ids that i actually specify so i'm telling it hey give me the kind of that information that i want to know carrying on so that's that basic interaction of what we're doing that makes sense we're adding them want to be part of the next commit now i just did a diff between two commits but there's other types of diff i can actually see so let's do my get status again so against this is a super useful command you might find yourself constantly typing that it's showing me how you have untracked files so let's add test file three so now it's staged if i do my get status again it would be part of the next commit now i'm going to change test file and now i'll do line three save that to a get status so now i've got a file that's in my working directory remember we've got those different levels so i have a file with my working directory that's not been staged and have a file in stage that has not been committed that's my current status on the system now what i want to do is actually look at those so here if i do a get diff dash dash cached so what this command is going to do this is showing me the difference between the current commit in the repo and what is staged so that's get diff dash dash cached so if we look at these different types of command i can do to see the differences between them between these get diff dash dash cached and you'll also see i think you can do staged which is just another command but it's basically doing exactly the same thing so to see the difference between staged and the last commit in the repo git diff dash dash cached now to see the difference between working i my file system and stage is just git diff so here it's just saying hey you've added kind of line three so i can see that in there with that so from this point over here i'm that so what what is that command doing so this is between these so that is just git diff what about if i want to see the difference between what's in my working and what's in the repo well between these i can do git diff and it's head remember what is head head is just a pointer to the branch which is to the latest commit so i'm saying the difference between my working and the latest commit and if i go and do that as well we jump over here if i do get diff head it's the sum basically of the above two so i can kind of see both of those things test file three and the test file so i've really kind of summed those differences all together what about if i want to remove things maybe i've put something into staging and i oh i didn't mean to do that i actually want to get it out of it i can actually do the get rm command to remove something from staging so here let's create a test file for see if i go into here i'm going to create test file for actually before we do that let's clean up a little bit let's do get status let's just do a get add dot git commit m clean i would put a more useful comment get status so i'm clean right now i get graph i now have four commits remember it's moved up again it's got all those files so let's create a new file test file for testing save it just by the way if we actually looked now in our get folder and our objects because we've done lots of commits and lots of trees and lots of blobs we have more and more of those subfolders because it's sharding the data across them there's add test file for and then what we're going to do now is i'm going to commit adding it so that's that actually committed it to the repo now what if i actually want to remove the file if i do get rm test file 4 it's going to essentially stage the delete of the file so remove test file 4. so get status i've deleted test file 4. if i do ls it's actually deleted from my local file system as well and now if i actually do a commit it will actually now remove it from that tree that gets created that's actually removing a file so what am i saying here is look there's a file that i have i actually want to delete so what i can actually do is with the kind of the get rm command i'm staging i want to remove kind of a file and it will remove it kind of from here as well and then when i do the commit it will remove it from the next actual tree the next commit so i can remove things from the repo as well now the history will still have it in the previous commits the previous trees but that's actually i can actually remove now i could also just delete it from here and then do a git add dot and it will see it's gone and it will do the delete that way so i can also just do a git remove um what about cleaning things up um what about actually i've put something in staging but now actually hey i've changed my mind i don't want it in staging anymore i want to kind of reset where things might be maybe bring down the last command dancing my working directory i don't want that there anymore so there are ways i can actually kind of go back and bring things back or remove things from the staging so let's kind of take a little look at those so if we jump over what i want to do now is kind of clean some things up so firstly i can do git reset so git reset is actually doing dash dash mixed by default so this is basically going to unstage anything now what it is not doing is changing anything in my working directory so let's clear this for a second and let's just make a change so let's code testfile.txt we'll add a line four and save it so now we'll do a get add dot get status so i've staged it it's in the staged area if i do git reset and now to a get status it's not in staged anymore now it has changes not staged for commit but the change is still there in my local file it's just i would have to restage it to get reset what it's actually doing behind the scenes it's actually making my staged folder match the last commit so i think about this picture here if i want to make my staging actually map i want to undo everything i've done well i can do get reset to get reset makes staging match the last commit ie a clean state i could also do um and we'll see this let's jump over so i can also do a git reset dash dash hard this would also change the working directory so if i do a git reset dash dash hard and now look at my test file my line four's gone so i've now essentially reset to the last commit so realize just be careful that that could be a dangerous one now i'm essentially if i if i haven't got that work anywhere i have now lost work i've reset it back to the last commit now there's things i can do in terms of stashing things and modifying things so there are things i can have but just be aware and be careful i'm essentially now bringing that back into making my working directory match that as well now instead of maybe having to bring back everything from stage to match last commit i can be more individual so i can reset individual files so let's change test file again a new line four and let's add that to staging again look at my status there's a file waiting to be committed i can do git restore dash dash staged from the last commit but do not change working to get restored dash dash staged says update staged with the version from the last commit so my get status will now show that files are unstaged again i could also restore my working from the stage so i've reset staged i could actually now restore that to my working folder so git restore test file and now if i look at my test file it's gone it's now actually gone back another now also i've got here hey look you could restore to stage and working by doing dash dash stage dash dash work tree in one and this is kind of showing me hey the full version is i'm telling it the source but source equals head is the default anyway so i don't have to do that so this is more about bringing things back so hey i can do a git reset i can do a git restore dash dash staged file she's going to bring it back from there i can also do a git restore file to kind of bring it back that way to bring the working in line so basically there's a whole bunch of different things we can do to move things around but it's really just interacting with those different levels hey i've i've done something i didn't mean to hey i've edited the file in my working directory oh i didn't mean to do that i just want to go back to the last commit yeah i can do that thing i want to go back to remember stage is typically going to match my last commit unless i've staged things for change so bringing your fingers from the stage typically will be what was ever in the last commit unless i've already prepared something that i'm about to put in to my next commit so that's kind of moving things around but remember all we're really doing is manipulating hey the the blobs or changing things in my working directory but don't ever panic there's nothing really in get that there's not a command to clean it up hey i've staged something i didn't want to hey i can reset stage back to the last commit or i can restore individual files i've staged to the last commit or i can restore everything if i want to delete a file in my next commit hey i can just do a get remove which will stage a deletion and then commit that and it will remove it so it's very easy to really kind of interact and modify those various things there's never anything you're going to get in some terrible state for the most part it it seems intimidating so you realize hey i'm just really moving different things around that's all we're doing now quite a few times i've talked about a branch and remember what is a branch a branch is just a name that is a reference to a commit as i do new commits it references the newest commit in that chain because when i do a new commit hey it has a parent link to the commit before it so branch is nothing more than a reference to a commit id that's it when i do a commit it moves with it i am working on a certain branch at any one moment in time that is head so head just points to the reference which points to the commit remember that there's nothing more complicated to it than those things so if i have all those things together for a second so i can think okay a commit i got the gold pen someone commented there you know let's get serious if i bring out the gold pen so i have a commit remember the commit just is a 40 character hash when i do a new commit it creates a new 40 character hash and it has that parent that points to the commit before it and then i do another commit it's a new hash and it points to the parent before it and it points to a tree which points to the blobs we have all of those various things remember that's all we're doing as part of this so we just get this chain and what's happening is hey if this was called main there's a reference that points to the commit id and then there's a head which points to the reference as i do a new commit hey i'm going to do a commit creates a new hash reference is the parent all that happens is this moves along that's it that that's everything that's happening as i do those things so i do the commits creates a new commit point to a new tree point it to the blobs moves the chain along and we see that the get graph remember that command we ran looking at the get graph really kind of showed exactly that so if we do a git log i can see the detail of all of the various commits i've done quite a lot to it all these changes i like get graph so there we go look all these different commits we have now what about if you want to undo a commit i've done a commit i didn't mean to joe i committed saying i don't want in there anymore well what's a commit it's it's a hash and a tree but really to be part of a branch is wherever the branch is pointing to so if i want to basically remove a commit from history i can't edit this it's immutable it's that sharp but what i can absolutely do is i can say you know what i don't want that there i can say git reset and what am i doing i want to move this over remember head points to my current branch i want to go back one when i go back one soft now soft means i'm not going to update my working directory or anything else it doesn't change staging doesn't change working so if i do a git reset what it's going to do is move this back so now it's here so this little kind of tilde there means go back one generation if i did to it go back two so now this wouldn't point there anymore and nothing remember nothing references that way as soon as i move my pointer to now point to this one before nothing ever references this this essentially is just floating out there there's nothing using it so it's actually kind of dead at this point so when i run these commands if i do that dash dash soft it only influences the actual repo level remember we have kind of the repo so let's just draw that out we have the idea of kind of the repo we have stage and we have working directory with those three levels so we get reset head soft just moves the pointer back actually on the repo so if we go and look at that as an example so run my get graph again so this is where head and my main is company pointing to this commit now what i'm going to do at this point is i'm going to reset head kind of tilde one get graph i've just moved up one now i'm pointing to c2 5 which used to be the one below head so we can see here this used to be head remove test file for now if i actually go it's adding test file for so we've essentially moved back one but it didn't change staging so as far as staging is concerned what is in the staging is hey look you've set up a deletion deleted test file for that you've not committed so staging still has that change if i was to look at my file system i do not have test file for now i don't have to do that kind of head tilde one i could actually reset back directly to the hash id i just did head tilde once it was easier to actually work now i can also reset staging now notice what's happening git reset dash dash mixed we have seen this before earlier on i talked about resetting staging and i said we're going to copy from the repo git reset and it wiped away staging well if i just do git reset remember i said dash dash mixed was the default if i don't specify like a previous commit it's just going to do the current one so i'm not actually moving it backwards but i'm saying reset staging as well so essentially over here if i do dash dash mixed it's also pulling that change down into staging now i could do git reset head tilde one dash dash mixed and it would go back at the same time in update staging likewise i can do hard which will also bring it all the way down to the working directory as well so i can pick how far i want to kind of revert things so maybe i committed something and i wasn't ready i didn't mean to commit that yet so if i just do a git dash dash soft it moves the commit back but it leaves my working and my and staging alone so i can modify whatever i need to get and commit again if i want to bring staging back as well hey i can do dash dash mixed to bring back staging also to match the new commit that i want if i don't specify a new commit hash it's just leaving it where it is here and in this case it's just now making staging look like that last commit so i can do kind of clever things if i don't actually roll back other parts of it so that's all we're doing here but i can manipulate those three different levels so dash dash soft i'm telling it a new commit id that i want the pointer to now reference these now essentially become orphaned away eventually they'll get garbage collected mixed also update staging with whatever i point to head one could be the current one whatever dash hard bring it back to my working directory as well potentially there i might lose work so you want to be kind of careful with the dash dash hard so here is my kind of get status or different things so i do mixed unstaged after reset if i do my get status so now it's now what it does it knows hey look you deleted it from your current folder but it's not staged this deleted test file for if i also now did a reset hard it actually brought test file for back on my local file system it's rolled back staging and working to what currently the head points do so i've now reset all of them and again i can do them all in one go if i went back another one so if i do my get graph remember the last thing i did was added test file for if i do a get reset now i'm saying hey dash hard so and staging and working i want to go back another one let's go back one generation so now it should be clean if i run this command now i point to clean and there's nothing staged if i look test file 4 is gone because now i've gone back past the commit where i actually had that file existed now all those other ones are now kind of sitting out there they'll eventually be garbage collected up okay so that's kind of a cool key point we're going down the different levels before we talk about more advanced kind of branching and other things sometimes i'm going to have a certain version or thing that i just want a point in reference and what i can actually do is create a tag now remember my head remember it just it points to a commit so if i can actually do hey what is the type of head well head is just to commit remember head points to the reference which points to the commit if i look at the content head just points to my last commit clean i can see it kind of down here a tag is a way for me to create something and by default at my current location so i can do git tag v1.0.0 if i create that look at my graph i now have a tag where head company points to i could also add a tag to a previous commit so i could actually take the hash id here and i could do get tag v0.9.1 i could also add it to like two versions back remember i can always use that head hey let's go back two versions and i might call that um 9.0 if i do my get graph and i've got these little tags now these will last kind of forever i've now tagged those various things what's nice about this is i can list my tags so a tag is a great way to reference a particular commit i can use it like any reference hey show me version 1.0.0 there we go i can absolutely see that thing it makes it easy to view i can actually go and have that now that is called a lightweight tag that tag itself has no separate metadata it is it's nothing really more than a reference there's also an annotated type now an annotated type lets me actually add for example a message so here i can add an annotated type and give it an actual comment so if i go let's look at my get graph again what one don't i actually have a tag and i could give multiple tags let's just pick our first ever one so if i just put in that hash there and run that line i've now added that and what i can do now so let's just do a git graph again so they've all got these little tags now now the interesting thing that's now going to happen is i can show it but notice a little bit of a difference when i do a get show on the tag there's this initial information now showed the tag shows as an object and then it shows the commit object that's not what we had with the first one the first one just showed the commit message and the reason for that is if we look at the type of an annotated tag it's a type of a tag if i look at a lightweight tag it's just a reference to the commit so it's just a way i can do like a head there's other things i can do with annotated tags there are things like some signing things i can do so there's a whole series of other capabilities that i i may want to do depending on what i'm actually working with a lot of times we'll use the lightweight tag but realize hey there is this more powerful annotated type if i was using a remote origin just to be aware a remote origin tags are not copied to it by default so i would actually have to go and push the tag so get push dash dash tag will push tags to some remote origin will actually cover that later on so let's actually talk about these remote origins for a second um very often even if it was just me on my own i probably want a remote copy of my repo now i can have them as private doesn't mean i have to share it with anyone but it's really the idea that hey scroll up here a second yes i have my copy of my repo but if i want to maybe that other people can contribute it or just for for safety's sake i might absolutely want a copy of my repo up in some other service again could be github azure devops it doesn't matter so what we'll actually do for our repo we set that copy as a remote now the common naming is remote origin it doesn't have to be called origin it's just the standard name for hey if i've kind of got a copy of another repo it's the origin so we'll call it it's a remote from us and it's called origin now this happens automatically if i perform a clone so there's a public doesn't have to be public there's a repo somewhere and i do a get clone it will automatically be set as the remote origin or if i create a repo and then go and add like an empty remote repo that i want to set as the origin i can do kind of a get remote add and at that point i would actually go sorry remote origin add whoops i have to give it the name that i want to be called origin add and then the kind of the url or the location doesn't have to be url of what i want so now i kind of establish this relationship and there's kind of a another option which i'll talk about later on now when i do these things when i use these repos then there's various actions i can do to kind of push and pull them to actually synchronize that various data and we're going to look actually into that now i'm not going to go into the detail on this now realize if i'm using things like github and i want to push to it well that needs to be an authenticated action so github has a whole set of different ways to authenticate azure devops has itch ways to authenticate maybe it pops open a browser and i'll authenticate once and then it stores that maybe i create kind of a access token and it uses that and it can store that and kind of for windows or cred there's different options to configure how i authenticate bitbucket azure devops github will have great docs to walk you through that i really wouldn't worry too much about that um git actually has a get credential manager now for the most part we'll actually probably leverage that but what we'll do just super quick is let's actually kind of look at the remote origin side of this so if we jump over firstly i can just show you so if i jump over to my devops master class folder for a second if i do a get remote dash v i can see hey look yeah there's this github john the brit devopsmc.git is my default for fetch and push i can see i called it origin for both and i can kind of see that url that i'm actually specifying for that so let's jump back over to my my play around and right now you can see i don't have any remotes now at this point it's super easy if i go to here's github and go to my repositories and i can create a new repo so i'll just call it get play one i'm gonna make it a private repo i'm not going to put anything in it i'm just going to say create repository and you can do this for free now it's giving me things that i can do and what it's actually saying is hey look you could push an existing repository from the command line it's giving me the two commands i need git remote add origin and then git push dash u which sets up a relationship in the future so i can do a parameter less push and pull i don't need to do the get branch dash m main because my branch is already called main but it's telling me hey these are the commands you're actually going to need to run so if i jump over so here i can do my get remote add origin from here so okay let's add my origin git remote get graph company i don't seem to know anything about any remote kind of branches well i'm gonna push origin my main branch so now actually pushed so what did i do originally i added that as an origin but there was no content yet so now i've actually pushed to it the content and i'm linking up hey main so now if i do my get remote again yep so now i've got it's out for fair and push it's set up for this one now if i was to look in that repo if i refresh it has my content so it's got the full history it's got all the commits it's a full copy of that but there's no tags well i have to push the tags get push dash dash tag and because i did the dash u it set up a parameter-less push and pull so now i can just do get push dash tag it's pushed up the tags now if i refresh it knows about four tags and they're all there so i added a remote to my existing repo it has the full code it has the full repository so we now have this full kind of status between these but they're not directly connected through any kind of mystical magical way that's going on i constantly have to kind of bring these things into sync so let's let's actually think about this for a second what we've done so what i had but if i think about those locations so on my machine i had a bunch of commits oops let's do a different color don't like that let's go back to blue i had a bunch of commits i'm not going to draw them all let's say i had three commits i had that up in the sky it didn't know anything now i had my branch main which was referenced by the head what we did remember is we did the get push when i did that get push it then populated the other repo with a copy so it now matched i had the same thing and once again it had kind of its main it has a head as well so new people to clone know which branch is kind of the default and that's kind of the idea around that now in terms of what's going on i'm gonna move over a little bit and run out of space i have to pull and push and fetch things because there is no ongoing really background synchronization going on i have to do the things so let's let's say for example i actually made a change up here let's say up here i went and made a change directly i did this and so now this main and head well they actually moved over to now point to that and we can do that okay so let's jump over and one of the cool things i could actually go into the file test file i can actually edit in here ooh line four from github and notice it lets me do commit changes extended descriptions commit it directly to the main branch go so now what's happened is this is actually in advance of my local copy now if i do a get graph notice so what actually there's some interesting things going on with the new version of git actually origin knows knows it went ahead it seems like every couple of minutes there is some kind of little sinking so what i would now need to do if i actually wanted that information i can do a get pull so we get pull and if i now do a get graph one word they now match so i've now pulled down and essentially merged it into my local copy so if i go back to this picture what i've done here is git pull so now i have this as well and once again now it moved me over now get pull is actually doing two things it does a get fetch and it does a get merge so get fetch is about hey telling me what changes have happened so essentially i'm saying get pull but it's really doing kind of a get fetch and then to move the changes it knew about to merge into my branch it kind of did a get merge to then move across so get paul combines two things tell me about the status what it knows or what it has and then i like that i want to move my branch along to match it as well likewise if i make a change locally on my machine well if i want it to know about it remember i would have moved my pointers to go up to the remote server i have to do a get push so it goes the other way as well so we can see those so here let's go over here if i quickly says me saying i've got the fetch content is on the box i've merged it together we can see on the get graph if i likewise made a change locally so best practice always pull first to make sure there's not some change on the origin before i make a change i could then edit the file line five locally save that and then i'll commit that change so remember that's all locally get status our branch is ahead of origin main is telling me you're ahead of the origin get graph would show me hey look i'm ahead get push and that pushing it up to the remote repo to get status will now show hey i'm in sync get graph will show they're pointing to the same thing and likewise if i change tags i could do a get push tags so that's kind of that key point and if i go and look now if i was to actually refresh now it's got my line 5 locally it knows about the updates it has that full history so all of that is in play looking good okay sometimes i'm going to have files that i don't want part of the repo remember we have this whole working area idea i might have log files i might have debug files and i might want to be able to get add dot and get a dot would add those files to it as well that's kind of a sad day i'm going to mess around i just don't want to deal with it so one of the files i can actually create is something called dot get ignore and anything i put in dot get ignore get will ignore now i would want to commit get ignore because i want other people to be able to get that and take advantage but locally on my machine it won't use that content it won't try and stage it or do anything like that so in my root folder i'm going to open create a file called dot get ignore and i'm going to say ignore anything star.log and ignore anything debug star and save that now at this point i could absolutely add if i do a get add and commit i've added an ignore file i'll push that remote and so i should be clean let's create a log file testing yep and let's create a file in the debug subfolder testing i can see the files are there do a get status i'm clean it's not saying hey look there's a log file or there's stuff in debug nope i'm all good it's ignoring that content because it's part of my dot get ignore file so now i want to talk about branches and what we're going to do is actually start fresh so let's go up a folder up here we'll create a file called jl repo we'll move into that folder we'll do an init and a status so nothing in it is completely empty and what i'm going to do is really quickly i'm just going to create a csv file and in that csv file i'm just going to create a few lines so i'm just going to we'll worry about who they are their powers and i'm just going to have a blank line in there so we just got 2 in there save it and i'm good and i'm going to add that file and commit it so at this point what i've done is i've created a repo and let's find a nice space we're going to work from so we'll go over here okay so what did i just do i created a new repo i have one commit my first hash it has a default branch main that points to that commit and my head pointer what i'm working on points to main that's where we are right now now when i think about working long term on projects we have this idea of branches now remember a branch is just a reference to a commit it's nothing more than that we've been working with this already everything we've done when we commit was to main that default branch that we specified but i can have other branches which could reference other commits this is really important to understand because the branch itself is a great way that we can think about working and doing units of work the branch has no history it's really important to wrap your head around the branch is nothing more than a reference it's nothing ever more than that when i create a new branch it's a new file that points to a certain commit it's the commits that have the history because they point to the parent but its ability to kind of point to different commits through different branches lets us be able to work on different items of work i might be working on a feature then i'm working on a bug fix and i want to be able to jump between what i'm working on i can track different streams of work branches are cheap they're easy to create they're easy to delete and they give me some isolation because i'm moving the commit of that branch if i'm working on some different thing my branch is pointing to whatever commit i'm working on so i'm not being influenced or interfered with other work and what's very common is when i'm doing a change i don't do it straight onto main what i very typically would do is if we think about this idea that we have the main branch if i'm doing a unit of work what i'm going to go and create so there's a certain commits on main i will go and create my own branch where i do my commits and then i bring it back in i'll merge it into main likewise someone else doing some work maybe they took a commit off here they go and do a unit of work and then they bring it back in now one of the things you can start to see already is well hey look if we're working on the same files which would absolutely happen what if i changed the file here and merged so brought it back into the main branch but then i took this previous version and made change or you get merged conflict and you have to resolve them so there's some work involved which is why there's this idea of trunk based development almost daily you bring your changes back into the main branch you may get conflicts but you're going to find them early and often so they're small and easy to actually resolve now some companies will have like a big feature branch that they actually have sub branches off and then bring it only into main when an entire feature is complete they might then have bigger merge things to handle with but different companies will use different methodologies generally if i want to do continuous integration i need to constantly bring my code back in together so i can run those integration tests to find a problem and fix it early so i don't get streams of development going off for a really really long time imagine a scenario where i had tons of branches just spinning off that lasted a really long time and then a month later i brought them all back together well that that could be a fairly sad day for the second person because they may have changed a huge amount of work now there are different methodologies i can kind of try and bring changes in periodically but more and more companies today have the idea of coming back to this trunk-based development coming back into maine or at least a common branch then maybe gets brought into maine periodically but definitely use a branch for everything if it's a fix if it's uh work in progress if it's a feature it might be throwaway might be a junk branch you can use different naming strategies for your branches but the key part is as an organization pick one approach maybe i'm bringing it into the main every day maybe i have a long feature branch you may say well my code is not ready yet so what some people will do is use feature flags to kind of hide the functionality hide the path of that code until it's ready break it into smaller chunks so there's that ability to do those things but you as a company definitely need to make sure you think of a strategy okay so let's talk about using a branch then so as a company i have some strategy to use it so i need to create a new branch so i can imagine hey i want to create a new branch i'm just going to call it branch 1 which initially will point to the same commit so i can think about okay i want to create a git branch and i'm going to call it branch put it anything you want branch one so that creates the branch so let's go and do that so if we go to our code all i'm going to do super quick is if i look currently i've just got my main branch and the asterix the little star shows me the branch i'm currently on main i can see if there's any remote branches i don't have any i could look at all of them i'm going to do get branch branch one create a new branch my get graph shows me hey yeah your pointing head is currently pointing to main but branch one exists as well if i list them yep there's branch one main is still the one with the star that's the one i'm using i can do check out checkout has now switched me my head is now pointing to branch one now instead of checkout there is also the get switch command the git switch command is preferred because they're trying to separate units of functionality and check out as many different things so switch is actually a preferred option you can create and check out in one step with git checkout dash c branch one so what i've done now is if i look at my to move my head pointer over i do get switch or checkout branch one so that has now moved head essentially to here it's now pointing to the reference of branch one and that kind of isn't there anymore so that's all we've done it's just a new reference and then we would carry on working as we did before so if we go and look at our code at this point i'll make some commits so okay let's check what branch we're on okay i'm on branch once it's got the star and let's edit the file so we open up our file again okay this time let's add in wonder woman and we'll save it and we'll add it so dash p i'm just showing off here i'll actually show you the chunks of the file that have changed do you want to stage this yes don't really need to know that again that's just me having a bit of fun and i'm going to commit it so we've added wonder woman get graph notice now main has stayed where it is but now branch one has moved ahead likewise we'll edit it again and this time we'll add barry allen come on barry allen let's save that once again we'll add it we'll commit it and if we look now branch one is two ahead but the status is clean so what we've done now is essentially for branch one is what we're working on branch one is now had this commit then we did another commit so these pointers here are moving so the head in the branch one is going there and here so my current status is actually branch one and my head is over here main is still stayed over there and i can see those things in action so if we jump back to our code for a second i can switch over so if i look remember my current file system if i just type out jl.csv there's clark bruce diana and barry if i switch over to main type it out again clark and barry have gone because i've switched branches it updates staging and my working area as i switch branches so as a person could be working on multiple different things it's going to move between them as i work i can go back to branch one and my work is back again and my working directory is updated as is my staging now branch one at this time which essentially is two ahead of main now what if i want to actually merge the changes in doesn't matter how many commits there are between them i want to merge the changes together now if i look at my current picture for a second it's a straight line i've drawn it kind of downwards just to visualize but where i am is a direct descendant of maine so to catch maine up to merge in the changes of branch one into maine all i actually have to do is fast forward main to be here so i can actually do that super super easy i can just move main to point here and then it would have kind of caught up i would have merged main into branch one because it's direct descendant there's no complicated other paths there's no code that has changed on main i can just move the pointer forwards so the way we do that is i need to do a merge but what we can see is let's check the status again so right now i'm on branch one there's nothing to commit i'm going to switch to main if i look at the difference between main and branch one i can see oh okay yet there's diana and barry allen have kind of been added to it i am operating on main so i switched to main because i want to merge in branch one it says it's done it if i do a get graph main is now pointing to the same commit as branch one and i can actually look at which ones are merged get branch dash dash merge shows me which branches are actually being merged together so at this time branch one and main are the same i don't actually need branch one anymore i've made the change i did the item of work the item work is complete i don't keep branches just for the sake of keeping them there's really no benefit in doing that so what i could actually do at this point is firstly check it has been merged so i'd run a get branch dash merged i can just delete branch one it's not needed if there was a remote i can do get push origin dash dash delete branch one so my get graph will now show no sign that there was ever this other branch i don't need it it's not there so in terms of what we're doing to make this happen remember what are the commands we want to do well i'm operating on main so i get switch main and i want to bring into it the changes of branch one get merged one now this was the fast forward it could just move the pointer because there was nothing else going on sometimes i don't want to maybe i want to keep the track that there was this divergence in the history now remember perversion i can use tagging but i want to i want to know there was something else that was then brought in so if i think about that same picture again i'm not going to draw everything every single time so we had kind of the main and then we created the branch and what i can now do is do something called a no fast forward now what that will do is actually create a new commit if i do no fast forward it will create a new commit and this one will actually kind of have almost kind of two parents so this is i'm doing the same thing there's no any there's no complicated stuff here it's doing a git merge again i would have done it on main but i'm saying dash dash no fast forward and i'm doing it from branch one again and now the history will look different it's going to give me a different view of the history because i'm not merging them together in just the fast forward it's actually going to create a brand new commit so let's see that one in action so here what i'm going to do is i'm going to actually reset so i'm going to do a hard reset back in time and just because i kind of want to show you this in action so there's kind of that the merge i'm going to go back in time so i never made those changes so i'm now back at my initial version note you can do a re-ref reference log and it would show me i can still see the commit ids if i did say hideous i can kind of undo some of this stuff but all i'm going to do is super quickly i'm going to create a new branch again i'm going to switch to it i'm going to make my changes again to my file so i want to bring back in again my diner prince and barry allen i want to do this in two separate commits so i'm just going to save that one and then add it and we'll add the edit again we'll add in barry allen how did i forget to commit ugh sitting me it doesn't really matter but i kind of wish i had done the other thing i must have forget to run the commit um don't change it one more time strength and speed i'll make one more change just so i can see two commits just so it's consistent there we go so we're all clean this time i'm gonna switch to main again i've got the same changes but this time i'm going to do a git merge no fast forward i can still see they've merged together branch one and main but now my get graph looks different here in my get graph i can see okay well yeah they made these changes and then they merged it in together it's a new commit it didn't just move the pointer it actually created a whole new commit for this so it was a different type now i can still check hey are they merged together i can still delete the branch but now the history will still show there was a branch that's kind of a big difference here now what i'm going to start doing now is i want to make it a bit more complicated now the scenario of what we're going to do is well we're going to change main as well we're going to make it now so a scenario is similar to this but if i think about okay we've got our kind of our original main we're gonna go off and make our changes again and what we're actually gonna do is just rewind time a little bit so i don't have to keep editing the file so this is where we are what we're gonna do this time is on main we're going to make another change so now it's not simple i want to bring these together but it's it's it's not a simple thing because i have to combine changes from here and here to create this new commit so this is called a three-way merge and i might expect to get conflicts so when i do this i'm fully expecting hey there might be a little bit of work i have to do to kind of fix this and make it how i want it so if we jump over so what i'm going to do is rewind one step so remember remember my main is pointing to head now also the challenging thing right now is my main pointer kind of has two parents it comes from these two directions now in the past we used a little tilde sign now i'm using the up arrow the up arrow says go back to your first parent so this is going to reset hard to update my staging update my working to my first parent so now it's like i'm just sitting here i'm back at this kind of jl roster csv and i just realized i didn't actually mean to delete that branch um because now i have to do have to kind of do that work again so let's recreate the branch one i was hoping i actually could have avoided that if i'd have been clever but i wasn't clever so we'll make the changes for hopefully the last time i ever have to keep retyping these in so i've gone back i'll be clever the next time i go back in time i promise so we'll make the changes again so we'll save this time we definitely will add and definitely commit we'll add it again we'll save we'll add this is all familiar this is just operating on branch one so we're good and then we're clean what we're going to do now though is we're going to switch to main and we're going to modify the file now this time we're going to add in cyborg it's adding in cyborg and we're going to add it and commit it so in a more interesting situation so if you look at this so okay well maine has got its own change branch one has got its changes there is no direct path now to get branch one we're going to have conflicts so get status with clean i'm going to merge in branch one now what it's going to do is it's going to create a file of where there are conflicts and let me edit the file to decide what i want it to do so i'm going to do get merge branch one and it's telling me merge conflict in jlcsv automatic merge failed fix it and then commit it now if i now go and edit the file it's put in these pointers so it's showing me these little heads and the change that head has i my main branch then it's showing me the changes that are in branch one under this kind of equal sign now you need to go through the entire file and find all of these if i don't fix these and then commit it it will include these weird lines in my final file which i do not want so maybe search for five equal signs to make sure i hit all of these now what vs code does that's nice it actually lets me just kind of click a button this is not particularly normal normally i would have to go and hey okay so i would delete this line manually i would delete this delete that and delete this i basically make it look what is the version without the conflicts so i would go and create that and then i save it so it showed me where the conflicts were i've addressed them and then i save it now it knows hey you're in this unmerged path status so now i would add it and do the commit and now i have the merge i can see the full history still it's here but i've merged those things together so that's kind of a super powerful thing now what i actually want to do just for a little bit of fun so before i go any further let's actually see if this even works let's right click on it use the mouse so what i want to do is save a picture of this no no it works so we're going to take a little snip actually of what this looks like there so we've got this and what i want to do is actually paste it just next to that paste paste there we go i want to kind of put it next to it just so that we can see what it looked like when i did that action because there's there's another option there's also the ability to do something called rebase now that merge thing we just did is super super important it really is the keystone of the work you're going to do when i'm working in my branch i bring it back into the main i'm gonna have those merge conflicts so i need to know how to address those but there are other things i can actually do there are times i'm working on a branch maybe and there were changes to maine i want to bring it back into the branch i'm working on i want to rebase my branch on the current version of main now i ca i can't just magically do that what it has to do is look at the changes i've made and replay them over all of the commits that have happened on main so i'm going to get conflicts but i can do this thing called a rebase so if i think about what a rebase is going to do then we're going to have a rebase essentially think okay main had that commit then i made my branch change two change three okay then on the main branch someone made another change when i do a rebase it's going to work out what the changes were and replay them but it's going to be a new commit so what it's going to essentially do is take those out and it's still my branch but now my branch is going to be change five and change hash six because it's going to replay but it's gonna now replay over that one so i look at history it's gonna look like i created my branch off of that it's rebasing my branch so instead of being based on there it's based on here now i'm going to get the merge conflicts if there are things that are conflicting but i'm addressing it now so i'm minimizing what those long term when i bring it back in it'll actually be now easy so when i want to merge these together now when i actually come to do that well guess what i can do i could actually do a fast forward because now this as a direct path it wouldn't actually have to do any kind of complex thing hey there is now oops a fast forward to actually get to that point that's what's kind of clever about the rebase i'm doing the work here in my branch instead of doing the work when i actually come and merge them together so let's do this now what i am going to be clever this time hopefully and if we look again at kind of our graph we see that's all complete i can see i'm merged i'm not going to delete any branches or anything like that i'm going to reset back one now i'm on main so it's going to reset my main back to i added cyborg so this is the state i'm currently at but this time i'm going to operate on branch one i'm rebasing branch one that's kind of the key point about all of this so i'm going to do at this point i'm switching to branch one my status is everything's clean i'm going to rebase off main now there's merge conflicts which we fully expected so i'm going to go and edit the file and it's saying hey look these are conflicting i'll accept this time rather than manually editing it i can just say yep accept them both that was it replaying remember the first change that was replaying andy adding wonder woman so i'll save that and we can add it now i can continue it wants a commit message you have added wonder woman good if i now do my get graph there's my main and my branch one so it's it's now moved ahead it's now a straight line so we had that one conflict for the wonder woman i addressed it but now it's a straight line if i was to actually type out my file what would i expect now to see in it well i've got victor stone as well because i'm now based off of main so now if i look at my status on branch one i'll switch to main and i merge in branch one if we look at what's merged yep they're merged together look at my graph it's it's a lot cleaner so if we now go and take our little screenshot if this actually works for me so if we take our snip over here and we paste that in my history actually looks quite different by doing that rebase it was a much simpler merge operation because i could just do a fast forward and it makes it all look a lot cleaner than this so again if i had that long term maybe branch i'm going to bring it in i can actually do the rebase and good times i'm actually now built off of the latest version of another branch so the end result is the same file but i just did it a different way so that was kind of a key point now i would say i've been doing all of these through the get command [Music] there is also again i've been doing the vs code if we jump over to vs code for a second all of these changes i'm doing it has this great kind of source control capability here like if i was actually changing the file if i did code jl.csv up here and speed and smarts i don't know and saved it it actually tells me hey there's a change let's shrink this down a bit hey look jl i could click add here to stage it now it's the same git repo my get status now shows oh it's been staged but i can actually do the commit here i can hit the little tick to commit it's prompted me from message and changed barry if i do my get status it's just doing the get commands for me there's even a console i can look at the output for example of different things that's going on and if we look at get i can see all the commands it's running so it's using that behind the scenes and the git lens you see all these little blame comments and there's much more that get lens does it's a phenomenal tool really recommend you go and take a look i'm showing you all this without it but it'll make your life so so much easier one comment about that rebase never ever do it on a public branch if there's a public branch that other people are using and you rebase people will hate you people will hunt you down because you've changed history they've done all their changes on the original history and you've broken everything so rebase is fine for you and your individual branch never go and do it on someone else's it's a really bad thing to do there is a more advanced way to start messing with history there is an interactive mode i'm kind of hesitant to go into too much detail on this but if just quickly i can actually go and do a well i can do things like change the last commit message i can update the files in staging without editing it but one of the things i can actually do is i can do this dash i so i'm on this command right here that gives me an interactive hook so what i'm saying is git rebase hit screen bracket 3 says go back three generations and what this would let me do is essentially now this is get lens giving me this nice graphical view this would let me do things like well hey i could squash i could squash these two things in together so now it looks like they're one commit i could reword different commits i can do a whole bunch of different things so i'm just going to squash the flash and the wonder woman into kind of one commit now again there's a textual version of this if i just switch to text i just change the words it tells me what all the commands are down here i can do i have all these capabilities but essentially if i now kind of save this file now there might be conflicts that would have to resolve and it showed me hey look do you want to combine these two messages so i might say hey added wonder woman and the flash so i'll change the commit message now now it's going to create new ids again remember we can't mess with time about there being some track i'll save that successfully rebased so now if i do my get graph i've got this added wonder woman and the flash now i've still got branch one there which is why i've got this weird thing if i'd actually gone ahead and deleted branch one i wouldn't have kind of all those things hanging out anymore so that's kind of what i've kind of i can do over there in fact i want to check what was merged i'm just going to delete branch it's going to probably complain so i'm going to do a git branch a capital d i'm just going to kill that off so now i'm back to there so now you can see that clean hey did squash those things together for maine i i can rewrite that history from within there so there's some cool things i can actually do but they're interactive can be kind of dangerous so i wouldn't kind of leap into that too much the last thing i want to cover is a pull request because the naming is kind of confusing sometimes it's kind of like this pull request and what is it doing and it's really we're just going to walk for a very simple scenario really using the code we have already we're going to base this on the idea that i have my repo so we have john's repo and in that repo i have a series of commits actually let's give it a second we're gonna say i have two commits now i've got more than two commits it doesn't matter let's just say there's two commits and sometimes someone wants to contribute to our work so let's say we've got clark so clark in his repo can do something called a fork and when i fork this i get my own version my own copy in my repo that means i have full edit capabilities to it i can't write things back but by doing that fork i now have my own version oops of that repo so let's let's actually walk through this for a second so firstly what i need to do is i need to create that john's repo up on the internet so what we're going to quickly do is actually go back to our get over here and we're going to create a new repo so we're going to create a new repo called j l repo we'll make it public this time we're going to make it empty and create repository so create an empty repo all i'm going to do now is for my copy that i have locally we're going to add that repo as the remote and then push to it that's it so if we quickly now go and actually look at that again there's my file what we are now going to do is as clark kent clark kent is going to learn look at my repo so there it is as a completely different user clark is going to go and look at my repo at this point i'm going to go up to fork up here in the corner so i'm up here and i can hit fork as soon as i hit that it's forking the repo and now i'm going to have my own copy actually of this repository this is my version now the way i would actually use this is well i would probably now replicate and clone this down to my local machine where i want to work on this file so i would probably open up terminal so i've got terminal here on my machine what i'm actually going to do is run a various bunch of commands so firstly i'm going to clone it from that machine so i'll jump over to clark and we'll do a clone and it's created a clone so now i can go into that folder and there's the file i now want to make a change to that file now actually before i do that let's think about one other thing so if i look at my remotes my remote currently is gonna actually be take a look at this my copy of the repo so my remote is going to be clark but think about john's copy may have changes made and if i want to contribute to john if john moves the main ahead i'm going to need to get those changes as well because john's not going to do a bunch of work if i contribute so what i might want to do is add an upstream and i'm actually pointing to john's copy of the repo so i'm adding something called upstream another remote to my machine so now i have my default kind of remote for origin which is my copy of the repo in github and i've added john's copy of the repo as well so what that lets me do is if needed i could pull down changes from upstream i.e john's copy now what i want to do is also define my little git graph friendly function so let's call my little function if i look at get graph i can see hey i've got the origin main origin head fetch i could do a get fetch from upstream and now if i look at get graph i can see the upstream main so here i know good main has not moved ahead in any way it's kind of all at the same point i'm kind of good to go so now i'm going to let's make a change um so let's look at the code for a second and what i want to do well i don't want to make it into main if i made it into main then john's probably not going to accept that instead what i need to do is actually create a branch and that would be the branch that i push say hey do you want to accept this change so what i will do as clark is i'm going to say hey i'm going to create a branch get branch branch 1 i'm going to switch to it in here i'm going to make a change so i'm gonna make a change and i'm just gonna change who the flash is i'm gonna say the flash is not barry allen we're gonna say it's wally west we'll save that at this point we've made that change i'm going to add it to staging and i'm going to commit it changed flash to wally west so i've made that change and now what i'll do is i'll push it to origin branch one so we did a whole bunch of different things right there so let's think about where we are so we created a fork now on my local machine i did a clone so i had those two commits and this is main i then created a branch where i have made a change i have now pushed that branch up to my repo this is branch one this is still main so that's what we've done we took a fork of john's repo cloned it to my local machine created a branch made a change and then pushed the branch up to clark's repo now at this point i want to say hey john take my change so what i do is i submit and if you think about this is main i submit a pull request i am asking john to pull my branch one change into their main that's the process that is a pull request so if we jump back over and now we go back to clark if we go and refresh we can see hey we've got different branches and that was it's got this hey branch one so i can switch to branch one it gives me things to actually try and help um to do the various things i might want to do but notice it's saying branch one is a commit ahead of john the brit main do you want to contribute and it's saying open a pull request so it's putting it right kind of there in front of me saying hey there are things you might want to be doing here because i can see you've got this change and there's other things i can do i've got these all the clothes i can do compare and pull request it's putting up here i'm going to do contribute i'm going to open a pull request so here it's telling me what it's going to do it's saying it's able to merge they can automatically be merged it's showing me hey the base repo is john the brit main and you're trying to push in from clark the super jail repo that the branch won so i can write a whole message hey the flash has changed made this for you and then i can say hey create pull request and then it's saying hey look there's no conflicts it's just kind of sitting there only those with actual permission can do this merge so now me as john in my repo i can see there's a pull request up here in this tab i can select it i can see it's open change flash to wally west is telling me hey from clark branch one to main i can select it i can see the comment they made it's telling me there's no conflicts and i have steps i can do i can merge it i can squash it and merge it to make it just one commit instead of kind of two i could rebase so there's different things that i could do i could reject it but i'm gonna be like yes okay this works um sounds good i'm just going to say right now actually merge pull request confirm the merge and i can add a comment sounds good now as clock it's successfully merged and closed it's kind of updated automatically to actually show that so what it's gone and done at this point is it actually created two so when it was accepted yes it created kind of the three it copied that over but then it actually creates a four that's the actual kind of commit that it brought in so that's now there's there's a fourth commit actually on john's repo and we can see that so if i jump back over for a second so now i'm actually going to operate as me so remember this is on my machine not clark if i do get graph notice now it's got it knows that origin main is ahead of me i can just do get pull get graph one word and i can see but notice he did two commits it took the original commit from clark but then he did a new commit to actually mark the pull request so that's my history at this point i have all of that available to me now as clark i actually want to do a bit of clean up because if you think about it clark's machine has this branch but well hey there was this whole set of other work done because i want to fetch from upstream then i can delete my branch then i can push it to my copy of the repo there's a whole bunch of other stuff i probably want to do to actually clean up because my machine pretty doesn't know all about this so now on clark's machine if i go back to that terminal let's clear this up this is where i am so i want to fetch from upstream remember that's john's repo that's going to know that main has moved so now i know about this but i don't have all of that stuff so what i could now do is i could switch to main on my repo and i can merge in from upstream i.e john's main and notice it says fast forward it knows it can fast forward because it knows hey yeah you're now just a child you had that extra commit so my git graph would now hey show that my head main now points to the same as upstream main if i look at the branches that have merged it knows branch one and main have merged so i could now delete branch one don't need it anymore if i look at my status well my copy of the repo doesn't know about this yet so i could now push it to origin which remember is clark's fork of the repo i'm getting it up to date look at the status and then remotely would push the deletion of branch one so that's clark's copy so essentially at this point everything is back in order clark's copy of the repo locally and on my remote i now have the current status i might now delete this like this might no longer be required if you think about it if i created this fork so i could submit a change do i still need a fork of this it's now up to date i'm on the main branch that other branch has gone i have successfully completed a pull request one of the other things you might do when you think about pull requests is actually as john if i for example had my main branch sometimes we want to protect things i don't want people submitted directly into main i want them to actually do pull requests even within the same repo so i can actually go into settings branches and i can actually create branch protection rules so i could say hey you can't just pull into main you have to do a pull request um i require sign commits and then i can't force push i can't delete these things i can't merge these things this is really a way for me to lock all of this down and actually control branches where i need protection so this is a very important thing if i want to have kind of this collaborative space i want to enforce some kind of process is using these branch protection rules really will enable me to do that and so that kind of finished off that whole picture remember so we kind of added this upstream we did the pull but that was our pull request so that kind of brought all those different things the branches the fetching the pushes all of those things together now we covered a lot of stuff there was this was a busy busy one i knew this would be but it wasn't really that complicated it took time because we covered a lot of different things but it's fairly logical when you think about what you're doing it's all these ideas of objects on disks and references that point to things and i'm moving those around and synchronizing it with another copy so i can collaborate how conflicts might happen when i'm bringing things back together that's okay we'll get emerge conflict but do it often so it's not too painful it's a manageable amount of work so i hope that was useful huge amount of work as always please please subscribe and give this a like i hope this is useful go and try this out yourself you can do all of this yourself follow that script file follow the video and uh good luck you
Info
Channel: John Savill's Technical Training
Views: 18,598
Rating: undefined out of 5
Keywords: cloud, devops, git, version control, source control, github, repo, repository, azure devops repos, learn git, merge, rebase, 3-way merge, pull request
Id: hQJktcBzJUs
Channel Id: undefined
Length: 153min 20sec (9200 seconds)
Published: Tue Aug 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.