This is Haka Public Radio Episode 548 for Wednesday, the 9th of March, 2022. Today's show is entitled, make a custom git command and this part of the series, version control it is the 270th show of Klaatu, and is about 20 minutes long, and Karimaklin Vlad. It is make git subcommand with shellscripts and git refoss. Hey, this is Klaatu, in this episode, I want to talk about git, specifically how to create your own git subcommands. You may have seen projects in the past that have added functionality to git, so you install the thing, and then suddenly you have these new subcommands within git. Git is kind of famous for having lots of subcommands. I don't think there's actually that many, but it does seem to be enough of a joke in the world that someone created sort of a website where it would give you fake git documentation for a bunch of fake git subcommands. It was actually quite entertaining, but if you do type in git dash dash help, I guess piped into less maybe, it doesn't even fill up a screen, that's not that many. So there's Klaatu, git clone, git init, git add, git move, git restore, git bisect, git diff, and so on. So those are the subcommands or the verbs or whatever you call those, the second statements in a command that you use, I call them subcommands lately. Those are built in to git. And in fact, when you do a man, git space clone, for instance, you do notice in the name of the man page, it's git dash clone, and that applies to any of the subcommands. You can do a man of git space, any of the subcommands, and it brings up a man page for git dash something, but if you do a witch on git space clone, you don't get anything. So the git executable itself is that user bin git or wherever it is on your system, you do witch git, it'll tell you, and if you do for instance a file on that thing, on that executable, it is an executable, it's an else binary. So git is parsing as a compiled option within git, it parses what subcommand path you want to go down when you do git space clone or git space in it or git space whatever. I'm making this point because I'm going to do something different than that, but the principle is somewhat the same. Okay. So in order to create your own git subcommand, I guess I could mention that I have created my own git subcommand, and it's over on gitlab.com slash slacker media slash git dash portal, I think I'll put a link in the show note, I guess, but it's called git dash portal, yeah, it's a slacker media slash git dash portal on git lab, and it might even be merit on GitHub. Anyway, anyway, it's a git subcommand, so you type in like git space portal, whatever, and it does some things with some git hooks and some git commands and scripts, the point of it is that it manages the very lightweight way to manage large binary blobs in that are associated with your git project. So it removes binary blobs from version control, which admittedly is not something you normally want to do with git, and it was one of those things that was kind of particular to a project that I was working on, but continues to be particular to a couple of project types that I work on, so it's still a tool that I use all the time, and it's good because it keeps big binary blob information out of the version control that I do need, but it keeps those large binary blobs associated with the project, and there are things like git lfs and git annex, but honestly those were both, I looked into them, and they were both overkill for lots of different reasons, which I won't go into right now. Right being that I created this subcommand, and I wanted it to feel like part of the git system, I didn't want it to be another tool that people sort of had to remember to tack onto, onto a project, it should feel integrated into the rest of the workflow, it wasn't necessary, I mean it could just be an a separate command, but I thought it might be nice or if it just felt like another thing that you do in git kind of fits into the workflow of your git commands, you do a git add, a git portal, a git commit, that was the flow, and I felt like that was easy for people to kind of integrate into what they were doing anyway, so I wanted it to be, I wanted it to fit into, into git very naturally, and the way to do that is to make it a subcommand, making a script that you've written into a sub command of git is actually really, really easy, git makes this very simple, it can be, well it can be embarrassingly simple, it can also be quite complex, so I'm going to go over kind of two of them to give an example of what you might do, okay, so first of all before we go into into how to do that, I need to talk a little bit about git rev pars, so rev dash pars, rev pars is a subcommand of git, it's built in, and it's one that you may not have used before, you may have, I didn't start using it until I started doing a lot of git hook scripting, and then it becomes really, really useful because it gives you honestly kind of weird, weird functions that you don't really need outside of a script a lot of times, so for instance, git space rev dash pars, dash dash show dash top level, that shows you the top level of your git repository, and if you're a user, you're in a git repository, do you really need to know your top level, I mean just look in the directory that you're in, right? Well sure, but what if you're in a sub directory of a sub directory of a sub directory, the quickest way potentially to get your, you know, to sort of remember where you are is, well, honestly, PWD, PWD will show you where you are, and then you just kind of backtrack until you see the folder called myproject.get, that's your top level probably, but again, if you need to know exactly where your top level is, you can do a git space rev dash pars, space dash dash show dash top level, and it'll tell you, home, so slash home slash clattoo slash myproject.get, that's your top level, what is a top level directory? Well, it's, it's, it's the outer bounds of the git repository, as far as git knows, that top level is the, the start of the world, that's where the universe begins, git doesn't know there are directories outside of it, git doesn't know it's on your computer, git knows nothing other than the top level, and everything below it, so git rev show top level shows you the, the directory with a hidden dot git directory in it, and you can, you can actually see that hidden directory with another git rev pars command called git rev pars dash dash, git dash, and that shows you again the top level, and the hidden git level in, in the top level. This, again, seems weird if you're just using git, you know, you probably don't need that, you just go to the top level, and then you do an L S dash A, or something, and there's the hidden git folder, where you can just go into the git folder yourself, although you probably shouldn't. Okay, so another cool rev pars one is git rev pars dash dash show dash cd up, and that shows you how to cd to the top level, and, and so if you do, if you're in a sub directory of a sub directory, and you do git rev pars dash dash show cd up, it returns dot dot slash dot dot slash dot dot. So if you're going to do a cd command, and you, and you want to end up in your top level, git rev pars dash dash show dash cd up tells you exactly what you need to type in after cd. There are other functions to rev pars, a bunch of different functions, but generally what I want to emphasize here is that if git rev pars exists, and it's got a lot of useful scripting utilities, that will help you kind of get yourself above git, you know, it kind of gives you that sort of detached view of your git repository, which can be useful when scripting, and it can also be useful when you're creating your own sub command. Here's more about that, now that we know the git rev pars exists. So let's do a really simple hello world style implementation of this, and then we'll do a more complex one where we're passing parameters and things like that. So I'm going to open up a text, I didn't know I'm going to go to a demo directory, so I don't clutter up my hard drive. Okay, that's good. So I'm going to open up a file called hello no git dash hello dotsh, and the dotsh is somewhat significant in this instance. So do add a dotsh if you're trying this yourself. There are, you can imagine different ways to do this, but you'll see why I'm saying to specifically put a dotsh on the end of this one. So I'm going to just create this file shabang slash bin slash s h, and then I'm just going to write echoes quote hello close quote redirect slash temp slash hello dottxt that's my exciting git script. That's the function that I want to give my users so that when they type in git space hello they'll get a file in their temporary directory with the word hello and it's not very useful, but it's demonstrative. So now so that that that that file exists. So if I put that somewhere in my path, I shall chamodet first chamodd plus x git dash hello, and then I'm going to move git dash hello dotsh into some location on my path. I have a binary, a bin, a tilde slash bin directory in my home directory, and that's always on my path. So now that it's there, if I execute git dash hello dot xt, nope, I'm at s h, then if I do a cat of slash temp slash hello dotxt, I get the word hello, so that works. And now I'm going to trash slash temp slash hello dotxt, because I don't want it to confuse me later. I don't want a false positive. So I have no hello dotxt in my temporary directory now. I've confirmed the script works, but of course if I do git space hello it doesn't work. It tells me git hello is not a git command and that's correct. What I can do now is create a second to file, and this one I'm going to call just git dash hello, and in this file I'm going to put a shipping bin s h, and then I'm going to just give the path, I'm going to give the full path. You don't have to actually I won't. I'll just do git dash hello dotsh. So in this file, called git dash hello, I am simply executing git dash hello dotsh. Now because git hello s h is on my path, I don't have to give it the full path here. You can, if you feel nervous about it not being in your on on in the user's path, but ideally you would have an installer that would kind of manage the paths. So git hello, git dash hello, just launch just git dash hello dotsh. I'm going to now move git dash hello to somewhere on my path. So again into my tilde slash bin folder, and now if I type git space hello, nothing happens because I forgot to chamod plus x bin git dash hello. Okay, now if I type in git space hello, it doesn't tell me anything, but guess what, if I do a cat slash temp slash hello dottxt, there's the word hello, the file exists, even though I had moved it to the trash earlier. So this is a new version of that file, and that's how you make your own git sub command. So just to overview that again, what we did, we created one but one script file with a unique name, it could be anything. I mean it could be penguins dotsh or just penguins. It doesn't matter as long as it's executable long as it, as you can run this script, it's good. I prefer to call it something obvious, obviously related to the thing that I am building. So in this case git dash hello was logical, but I wanted to distinguish this file from the front end file. This is kind of the back end business logic part of what we're doing. So it's git dash hello dotsh. That's put into your path, created marked executable. Next, you need to create a front end file for git to find, and that front end file needs to be the incantation you want people to be able to type into git as a sub command. So if it's git, hello is what you want, then you need to make a file called git dash hello and put it somewhere in the path. When you then type git space hello, git knows to look in the path for something that matches that seek of that combination, and if it does exist, then git runs it. git dash hello resolves to git space hello and git. Now in this case, my front end script was quite simple. It just launches git dash hello dotsh. That's easy, but it can be more complex. So if we get portal for instance, I need to pass arguments. You don't just type in git space portal. There's other stuff you need to do. If you're going to add an image or a file to your portal, you do git space portal, space add space, whatever file you want to add to your portal. So I needed those arguments. I needed to know what action the user was going to take. Are they adding something or are they moving something? What are they doing with git portal? And what file are they targeting? So all those things needed to get passed through to the actual actual script that was getting run and the hooks and all the things that we're getting processed. Git rev pars is able to help you with exactly that. So if I go to git portal, I'll go into the file here. Okay, so here's the git dash portal command. And you don't really need to know what the git dash portal dotsh command is. It's a script. It has a bunch of different functions in it and and does lots of different things depending on what kind of input it receives. But none of that's like that's just detail work, right? All we know is that we got a black box here called git portal dotsh and it needs some input and it'll provide output accordingly. So the git dash portal script to launch that is it's only like four lines. Shabang slash bin slash SH arg equals dollar sign parentheses git space rev dash parse space dash dash sq dash quote. So sq dash quote is an option that git rev parse provides you to safely quote the rest of whatever command you're feeding it. So whatever is considered an argument or a parameter or whatever it gets quoted. So dash dash sq dash quote space quote dollar sign at a at sign close quote. So that's dollar sign at sign in in quotes and then close the parentheses. So the arg variable has just been set to the results of using git rev parse dash dash sq dash quote on dollar sign at sign which which represents to the shell that it it's the rest of the arguments and second line is command or I just put CMD because I'm lazy to more type CMD equals quote git dash portal dotsh space dollar sign arg close quote. So the command variable is simply executing git dash portal dotsh wherever it may be. I don't care. I have faith because the the the the user has installed this somehow. So I have faith that git dash portal dotsh is somewhere in their path. So I'm just calling git dash portal dotsh space dollar sign arg where arg is of course the result of that git rev parse command that I just went through. And then finally the final line is eval space quote dollar sign CMD close quote. That's it you're done. So if I just go over to a back over to my demo folder here and do a git init dot. All right, I guess I could have just done get a net now. I think and then I'm going to do, well, I need some content here. So I'm going to copy this pixel file that I keep handy from my home folder into my current directory. And now if I do git portal that is git space portal space ad space pixel dot png then now I see that in my current directory I have a new directory called underscore portal which is the default name of the of the portal. It has a sim link from pixel dot png into the portal. And that's how this that's how git manages this. So then you do a git commit pixel dot png. So you're committing the sim link rather than the actual binary file. And I didn't add that yet. Get add pixel dot png. There we go get commit dash in added a file close quote. And now I've got a git log that contains a record of me committing pixel dot png. But I've got a repo without actually that does not contain pixel dot png. It just contains a sim link to a known location underscore portal that contains the actual file. That's what git portal does. It's simple in theory and works actually quite well if you if that sounds like something you want to try feel free to try it to been working for me really well for several different projects where I'm dealing with either really really large multimedia files or I'm dealing with so many multimedia files that just don't really matter to me that much. It's just the fact that there is a jpeg in this location. So I use git portal quite a lot to abstract sort of the art from the craft and and it works out. I mean it it does remove things from version control. So if that's not something that you want, don't do that. But if it is something that you want, try it out git portal. And and either way, if you just need reinforcement of what I've just discussed in this episode, that's the repository to look at gitlab slash gitlab.com slash slacker media slash git dash portal. That's the that I'll have if you look in the bin file, you can ignore all the you know the auto tools and the configuration files and stuff like that. Just go to the bin file. There's git portal that's the front end git dash portal.sh that's the business logic. That's where it all happens. That's the application. That's the script. There are some hooks as well. So there are some things in there that that that you won't see. But I think that those two files together should demonstrate really really well what I've talked about in this episode. So I hope this helps you. It's really fun and and cool to be able to just create your own subcommands. Don't get carried away, I guess. But it is it's a neat little trick. Thanks for listening. Talk to you next time. You've been listening to Hector Public Radio at Hector Public Radio.org. Today's show was contributed by an HBR listener like yourself. If you ever thought of recording a podcast, then click on our contribute link to find out how easy it really is. Hosting for HBR is kindly provided by an honesthost.com. The internet archive and our Sync.net on this otherwise status. Today's show is released under a creative comments, attribution, share a like, if you need us old lessons.