As I continue to explore a few of the common git commands on this mini series I had to think back a little on one that does get used more than we probably think. At least for me that was the case. The git checkout
command is wild. Like magic wild. In the previous two posts I talked a little about the init and clone commands.
This time around I’m going to go over the git checkout
command. This is one that I think was bizarre when I first started working with git. I didn’t really know all the quirks and to be honest I still may not know them all. It is a great command to know to help you get out of bind as well. Especially when working locally. This was one command that has really helped me over the last couple of years in getting things back to working order. Or at least in unbreaking some things.
Updates files in the working tree to match the version in the index or the specified tree. If no pathspec was given, git checkout will also update
https://git-scm.com/docs/git-checkoutHEAD
to set the specified branch as the current branch.
Taken from the documentation page as you can see.
The really nutty part for me was when I realized what you can pass in order to get things back. Again, the thing to remember here is that git can be very powerful when it comes to file history. Retrieving a change made in the code or a file by passing a few arguments to the command line is super cool to me. There was one example where I need to roll back a version of a plugin but it wasn’t the previous one but rather almost two versions back.
The really cool part for me was actually looking more in depth at the source code. Yeah, it did take me a little bit to find where that resided only because I wasn’t super familiar with how it is structured. So, of course, I read the source documentation and came across the file that defines the command. It resides in the builtin/checkout file which is written in C. One language I am getting more and more comfortable reading.
The one comment that really helped me understand a little more was:
/*
* Extract branch name from command line arguments, so
* all that is left is pathspecs.
*
* Handle
*
* 1) git checkout <tree> -- [<paths>]
* 2) git checkout -- [<paths>]
* 3) git checkout <something> [<paths>]
*
* including "last branch" syntax and DWIM-ery for names of
* remote branches, erroring out for invalid or ambiguous cases.
*/
It helped me because it made me see that you can pass a path to the command. Meaning you can checkout a single file or even an entire folder. The tree being a git internal meaning, of course. The super cool part about that being you can checkout quite a few things. Especially if you need to undo in order to fix something.
I think that’s part of the reason I often times like to call git a super, fancy, elaborate undo tool.
Having the ability to pull in changes from just about any point within git is really great. This was one of the reasons I really wanted to dive much deeper into how git works. To better understand so I don’t fear breaking things as much and further hone my git prowess. The really cool part for me was when I realized that you could checkout entire folders from other branches and previous commits.
I remember one time I had to look up how to undo a commit. Yeah, there are plenty links which ‘show how to do that but I wanted to learn on how it works. The one command I saw was git reset
but it didn’t completely dawn on me what it did. I’m still at a lot of the commands so that will be for another post and another time. What I wound up using was something like:
git checkout [previous-commit-hash] -- path/to/plugin-folder
I then wound up committing the code and pushing things. It got me out of a pinch and helped me understand that I could do things like that. This was one of the reasons I really wanted to dive much deeper in the code of git.
So far I have really liked looking more and more into the source code to learn from it. There are still a few more commands that I will be looking into. I’m pretty sure I’ll be posting a few of those here as well since this is also how I learn more. By sharing what I have learned.
I may take some time and see about creating some random git hooks too for random usage and possible sharing so others might be able to get some benefit. We’ll see.
Comments
2 responses to “Checking on the checkout”
so inside the last example you gave “git checkout [previous-commit-hash] — path/to/plugin-folder” that commit is the associated code change, would it be best to do the whole folder in this instance or if you knew the file name of the effected code, would that be better? Not to say i am git genius of any fashion just trying to inquire deeper understanding? I guess? lol Love your blogs Jose!
Yes, if you wanted all the files which resided in that folder you would simply pass the folder path. If you wanted just a single file it would be the
path/to/file.php