 to my talk, this is going to be classy git, git like a gentleman. First of all, my name is Scott Chacum. I work at GitHub. I am the author of gitsem.com, so I'm going to show you a couple of resources that in case you don't actually know git, I can't imagine that this is going to be a fun session for you as we're not going to go over git really at all. So I'm just going to do it one minute. gitsem.com is a good place to download it. gitrep.org is a good place to learn about it. progit.org is a Creative Commons licensed book that you can read online for free. My Twitter is atchicum and my email address is atchicum.gmail.com. So if you guys have any questions or anything once having learned git, please do let me know. Okay, so that's more than enough about me. The notes for this talk are on bit.ly at classygit and the version of this talk is at gittips.robot.com. So I'm assuming that you probably won't want to take notes on this. We'll go over it somewhat quickly. So, I want to go over a couple of new things that have been introduced in git recently, so that things you may not know about if you're installing an older version of git or you don't keep up to date with it. First of all, short status. So, if you say git status-s now, git will do this. It will give you sort of a subversion style output, rather than the sort of long style output that git status normally gives you. And if you do dash b, it will give you the master origin master, a head six behind however many, so you can get an idea of where your branch is relative to the branch that it might be tracking. So, this is a fairly nice addition to the status output command, so it's not as verbose as it normally is. If you want to get a little bit of a nicer output on that, I recommend that tool. The thing that is new is word-diffing. So how many of you write text in that is version-controlled in git? Does anybody write some text? So word-diffing is a very helpful tool in case you're writing paragraphs of text. What normally happens when you run git-diff is that it gives you a line, contextual line-diff, so it takes off one line and adds another line. If you say git-diff-diff-word-diff, it will go to a word, it will do the dip by word rather than by line. So it will take out the word that was removed and add the word that was added. So this is really helpful if you have a very long paragraph of text and you're trying to, one line was changed, or one word was changed, instead of having the entire paragraph removed and another entire paragraph is slightly different added, it will just show you the word that changed. The other thing is git-notes. This is a fairly new addition to git as well. Git-notes allows you to add metadata onto commits without actually changing the Shah of the commits. You don't have to rewrite it to add something to the message. You can simply add some metadata that points to that commit without actually changing it. So for example, if we have a couple of different commits and we say git-notes edit on some Shah, it will open up a message. We can type in some message. And then when other people type git-log, when you type git-log, you can see that note on that commit. So you can annotate any commit that you want to. And if you push this to GitHub, we'll also show it in line as well, so there's support for that. And the only thing you can't do is you can't merge. So you can't use notes for right now. They're working on this, but what you can't use notes for right now is, say, commenting on something and then sharing it with somebody. Because if they comment as well, then you need to merge the notes together and it doesn't work very well. But what it is good for is writing automated systems that add metadata. So if you only have one right source, having automated systems like saying this build passed or something like that, but there's only one person writing the notes together because it is very useful for that. So that can be helpful. I can't hear my slide changing thing. I worked a long time on that. All right. The other thing, smart HTTP. So does anybody use get over HTTP right now? It's becoming more popular. This is actually fairly new, but git does have a better protocol for HTTP before you used to have to use the git protocol or the SSH protocol to actually use your data. SSH to do pushing. Now, and before it did support HTTP, but it was very, very dull. So what would happen is you would request something and it would go through a patch and it would just individually ask for stuff. And if it needed one object out of the pack file, it would download the whole pack file. So it was very inefficient. Now what it will do is it will do something much more similar to SSH where it will go. It will figure out how to have a conversation with the server. It will figure out all the objects you need. It will build a custom pack file for you and send it down. So it works the same way. So this will go through firewalls a lot easier. I think that most posts will be supporting this. GitHub has supported it for a while. But most posts will be supporting this as clients upgrade. And I think this is going to be the de facto way that git will be transferred down. So if you want to set this up if you're running your own git server and you want to set this up internally, git will now ship to the CGI called git HTTP back in. Then you can put it to Apache this way. It's fairly easy to do. And then you have read access to your repositories. And you can turn on write access and just use normal, anything that curl supports for basic authentication. So basic off, that sort of thing, for write protection. If you want to do this in Ruby, I also have a library called GRAC that we used to get up for a while. We've switched over to the Apache one, but we didn't use this for a long time. Where you can, actually, it's a rack app. So anything that is rack capable, you can load it in. As long as you have git on the server, you can then clone and possibly push over that rack app as well. So you can put this rack app in your Rails 3, in front of your Rails 3 application, something, and use your Rails app as your git server. Some older stuff. So that's the newer stuff that you may not have known about in git, but I want to talk about also some older stuff in git that a lot of people don't use or don't know about that I've found very useful. One is git describe. So what git describe does is it gives you a more human readable version of your git shaws than you would normally have, right? So if you want a human readable version, for example, to put in a message or to put in an email or something like that, git describe is a great way of doing it because it gives you a human readable version of a shaw that you can use in place of a shaw just about anywhere you can use a shaw. You can use it to create a branch off of it as though it were a shaw or anything like that. So if you say git describe and give it something that is a shaw or a pointer, it will give you back a version that's sort of human readable. So this basically means 25 commits after a tag, 0.2.4, and it puts the shaw in there at the end so that you can actually say, like if you email that to somebody, it is unambiguous. It means the same on every system, right? They can say git branch, my branch, and then put that and it'll start the branch there instead of having to send the shaw that's available to look at normally. So if you give it something older, it says this is six commits after 0.2.4. If you give it some random shaw, it says this is 46 commits after 0.1.4. Whatever, it doesn't really matter, but it does give you an idea of where that commit is relative to an own commit and it can act as a shaw. Like it doesn't matter whether you use that whole shaw or whether you use 0.1.4, blah, blah, blah. Git will treat it the same way, right? It'll parse it out and figure out what it is. So that's sort of a nice way of doing that. The other way that you can do is name rev and name rev sort of works the opposite way instead of finding some tag and saying how many after it is. It finds some tag or some branch or something that says how many commits before it is. So this will change as your commits change or as your tag moves. But you can give it a shaw and it says it's four commits after 0.2.0, for example, or you can say, I only want you to use stuff from the ref's head's name space. It'll say it's 36 commits after master or 36 commits before master. And you can say describe. So these are all describing exactly the same thing, right? The tags, 0.2.0, until they're four, the master 36. All three of these mean the same commit. It's just git can tell you, it can give you different human parsable ways of referring to that information, which is kind of easy. This is kind of interesting, you can set up aliases and just say git human on a shaw and it gives you something incredibly human readable. Everybody knows what that means, right? If you don't know that syntax, this is how you actually parse that. The tilde two means two first parents and then the, I'm sorry, the yeah. And then the character two means the second parent, so it's a merge and it's the second one, the one that was merged in, not the one you were on that you merged in. And then the first parent of that and then the second parent of that. So the way that you can walk this is the tilde two says, there's your restart, tilde one, tilde two, and then character two, this would be character one, this is character two, and then the tilde one is the first parent of that so you walk this whole line here and you get this one and then the tilde two or the character two is this one right here. So you can see 6507 is the one that we put in there. So that's actually how you parse that out. So that's pretty easy, right? Human readable, that's what I love about git. Now, you can also do something like this though, which is actually pretty cool. This is sort of my variation on human, which is human, which does the same thing but reads from standard in. So you can pipe out through it. So you can say git long, pipe through my little alias there and it will annotate all your shaws with some slightly more human readable version of them. So if you actually do one, version one, version two, version three, git does it backwards in this case, but you can git that type of thing if you really want to. A lot of people complain about this, but this is the way that I get them to stop whining about it. Now, the other useful thing is git bundles. All of these things have been in git for a long time, it's just that not that many people know about them. Git bundles I actually use quite often. Git bundles is basically a way of using a file as though it were a remote. And so what you can do is you can say, say that we have a couple commits and we want to send these commits to somebody over Snickernet, right? So we can do this with bundles. We can say git bundle create, give it a file name, and then give it a branch to start at. It will find everything reachable from that branch and it will put it all into a file and then we can email that file to somebody, right? So we have this file now and it's just a binary file we can email and we can put on a USB key or whatever. And then we can, so we transfer that to somebody and then the other person can do any operations you can do on a remote that you do with a remote URL, you can do on this file and it will work fine. If you want a less remote, you can just see what branches are there. You can say clone, you can clone directly from the file. Say I want to check out the master branch, put it into the repo directory and it will clone it and then you go in there and you have your git repository, right? So it's just as though you had cloned it from an actual remote URL and you just cloned it from this binary file. So anywhere you need to Snickernet something, bundles are very easy and very useful, fairly easy to do. If we add to that repository and we want to send changes back via a bundle, we can just bundle up the difference, right? Just the stuff reachable from master that's not reachable from where we cloned it from. That's three commits. We say create a bundle of just those three commits that gives us a binary file and then we can email that binary file back to the original person, right? And then that person can fetch it in if they want to. They can say get fetch and give it the bundle files that were URL and it fetches it from that and then they can see the stuff that you would do. So you can actually just send files back and forth if that is useful to you, which sometimes it can. Branch management. So there's some really useful branch management tools that not a lot of people know about that I use all the time. I'd like to share with you. If you say get branch, it gives you a whole bunch of branch names. If you say get branch dash dash merge, it will filter those branch names by the ones that are reachable from your current head, right? So wherever branch you're currently on, it will only show you the branch, when you say get branch dash dash merge, it will only show you the branches that have already been merged in. That it can find by walking through your history, right? So these are possible deletion candidates, right? You can delete these with get branch dash lowercase d because they're already reachable. You've already merged them and you probably don't need them anymore. If you say get branch dash dash no merge, it will show you just the ones that are the opposite of that, the ones that are not reachable from your current head, right? So you can have hidden work. You will have probably hidden work on all of these. And so this is a good way of saying here's some branch that I haven't merged in yet I may want to look at to see if there's something that I forgot to merge in from. And then if you have a commit at some point, you want to see which branches have that commit in them. You can say get branch dash dash contains it. Tag has a similar command. You can say show me all the tags that contain this commit as well. And that has come to reachable a couple of times. Okay, now I know that this is a little bit dense so what I want to do is take a short intermission, do something a little bit different to reset your brains and then we'll go back to dense get stuff. So this is going to be a quick gentleman's guide to being a gentleman. First off, whiskey. How many of you do not drink whiskey? I'm just kidding, I'm not going to make you identify yourself. Whiskey comes from an O'Gaelic term which means the water of life which I agree with. There are three different types of whiskey that I just want to tell you about because if you don't know whiskey and you hear these phrases you may not know what they mean so I just want to tell you them so that you are not giving people blank looks when they order them. One is a Scotch whiskey, it's whiskey made in Scotland. Bourbon is an American whiskey, it is made from at least 51% of corn mash and rye is made from rye, so these are all made from different grains. So if you hear any of these, they all mean whiskey. Now, they took me a while to learn them. Now, there are three different ways to drink whiskey. You can drink it neat. Does anybody know PJ Hyatt? That is his specialty. That means no ice. You can put a little bit of water in it that possibly brings out the flavor. Some people don't like that, because those people are mean. And you can drink it on the rocks which some people say dead is the taste of it or freezes the taste of it. I disagree with that. I think rocks look cool. Basic etiquette to being a gentleman. verbal grace. If you're a gentleman, you're nice about things. You're not mean to people. Like I just was. You tip well and you don't tell people that you're tipping well. You don't want people to watch your iPhone when you're in company. How many people know people who do this? They're not gentlemen. Take your hat off when you're indoors and you offer your seat to women and children. Okay. Finally, actually two more things. Have a treat a lady. Always open doors for ladies. This is very important part of being a gentleman. Give up your seat again. It's very important. Stand in the lady's room. How many people know somebody who does this? See? This needs to be, this needs to be, this is a talk that needs to be given. Offer your arm and pay the bill and take the screening when you're at it. Now, the final thing, and I know that this is necessary from looking at the room right now, dressing like a gentleman. You always wear a slack. It can be pleated. It can be flat front. It doesn't really matter. But you wear a slack and the plus is they're very comfortable. You always wear a coat. You do not bottom the bottom, you do not button the bottom button and the other thing about a coat that's cool is that you can keep your wallet in here. And finally, you wear a hard shoe. If you take nothing else from this talk, always remember a gentleman wears a hard shoe. Alright, now. You are confused by tracking branches. I am confused by tracking branches as well. I hate them, but they are a necessary part of using it. And if you learn them, they actually can save you a couple of seconds. So, adding all of that confusion, I think it's totally worth it. Now, if you fetch through in a moment and you get a new branch down, so in this case, frots, you have a new branch that somebody else has added. You did a fetch, you get it down locally. You want to set it up to be tracking so that when you say get push origin, you don't actually have to say get push origin master because those extra six keystrokes really take up your time. So what you want to do is you want to set it up as a tracking branch. Now, here are five common ways that people try to set up tracking branches because you have this new branch. It doesn't automatically set up a tracking. You need to tell it to do that. So, one, you can say, get check out origin frots. This will detach your head. That sounds incredibly painful. And it can be. What that really means is that your head is not pointing at anything. So when you do new commits, they will go into the system but no branch goal will move forward with it. That's what a detached head is. The only person in the world that I know that uses this effectively is the maintainer of Git, which is the only reason it still exists in Git. That Git even allows it to do it is because the maintainer loves it and nobody else does. But if you do that, it will say detach his head and you're like, I don't know what just happened but I think somebody died. If you say get check out dash B and then a branch name and then a remote branch name, it will set that branch name as tracking automatically. So this is the best way because I think this is the clearest and sort of most straightforward way of doing it. That's fine. If you say get check out dash T and then a remote branch name, it will give you a local name, a local branch name fraud that is set up to track. So we'll just copy the name. So that's okay. If you say this is the worst one because this is the most magical term that I've ever seen in Git, if you say get check out the name of a branch name that's in a remote that you don't have locally, it will assume that you want to create a tracking branch for that. So it does a lot of assumptions there and it's super confusing. But if you add a dash T to that, then it says, I don't know what you're talking about. So I would recommend using the second form because I think that is the more do what I say version and it's the least confusing. But this is the cheat sheet. I have to look at this basically every time I want to set up a tracking branch even though I've been doing Git for several years now because it always confuses me. But I wanted to share that with you. If you set up a local branch name fraud you set it up and you want to set it up as tracking when you push it to a remote it does not automatically set it up as tracking. You have to still tell it you want to track it. So the way that you can do that now this is a slightly new thing in Git as well because you can say get push dash U origin frauds and that will automatically set up your branch as a tracking branch to wherever you're pushing it to. So this is actually fairly nice. Update my local version to be tracking. Alright now if you if you do have tracking branches there's a couple things that you use them for one is to pull it when you say get pull it will do the fetch and it will automatically try and merge the tracking branch in so that's sort of a general use case for that. The other thing is that if you say get push origin you want it to push to the tracking branch generally. But that's not what Git does, right? Even if you have a tracking branch set up and you're on that branch and you say get push origin it will not necessarily push your branch to a tracking branch to whatever it's tracking. What it will do by default is it will the first one is actually what is by default that setting which is matching. It will try and push every branch you have locally if you say get push origin it will try to push every branch you have locally to matched named branches on the system you're pushing to. So it will find every branch that is named exactly the same and try to push all of the local ones to all of the remote ones. That's what get push origin will do by default. If you want to change that behavior you can say push dot default nothing which means if I say get push origin assume that I mistyped that I don't know what I'm doing that I've been drinking too much. If you say get push origin you have push dot default set to tracking what it will do is what you probably expected to do which is it will push your tracking, your current tracking branch the current branch are on to whatever it is tracking, right? So whatever branch is tracking even if it's named different that's probably what you think get push origin does by default right now. So if you do just set it to that so that you don't have to change your mindset. The other thing that you can set it to is current which means take my current the branch I'm currently on and push it to a branch named exactly the same thing on the server. So if it's not set up even if it's not set up as a tracking branch it will push to the same name branch on the server. So those are all fairly useful. Okay replacements replacements are also useful. Does anybody have a give repository yet that is incredibly big? Okay the starting did it start out big or did it get to that thing? Okay so replacements might be useful for you. I will show you an example of a large open source project that uses replacements or a system like it but what replacements allow you to do what replacements generally allow you to do is replace any object and get with any other object and get. So you can basically say every time you get listen every time you see this shaw instead of getting the object that that actually is get this one instead. Yes? No this is a replacement for graphs. So I'll show you a little bit about graphs as well but basically at the lowest levels of get that's what it will do is it will say every time I see this shaw I will pretend that I'm giving the content for that shaw but instead I'm going to give the content for this one. And it can be any object it can be a commit it can be a blob it can be a tree it can be a tag it doesn't really matter you can just say replace this one with this one. There's a lot of stuff you can do the most common way that you guys are probably going to run into is to be able to graph history together. So if you have a very large history what you can do is split it and have a working history and have a historical history that doesn't make sense have a working history and have a archeological history right? So let's say you have a big history you want to split it up what you can do is you can say you create a pointer to some place that you want to be the first part of your archeological history you say so in this case I have my master branch on the top I have my history branch on the fourth pin I want everything from four down to be not necessarily cloned by default, right? I just want to get the last couple minutes. So you create a branch there and then you can add some remote so project history and push your history to that so you have two URLs one for your project history and one for your sort of current working history your current working project does that make sense? I may not have explained that well what you do is you split your commit history into two separate repositories one with just the last few commits that you can sort of work with and one with all the rest of your commits right? So this is just the beginning? Yes You can do it so anybody can do that with get cloned-depth, right? You can say get cloned-depth-depth five or whatever it's like the last five commits but that's up to the user if you want to do this on a project level because most people won't do that by default they need to know that it's a big history when they cloned so a lot of open source projects don't want to do that because people won't necessarily do that they'll just download this huge thing they'll give up when it takes they won't do something, right? So what they'll do is they'll split it up and say here's all the history you made on the or they'll import the last commit first and then put that out start working and get and then import the rest of the history later and then allow people to grab it on I believe Pearl did that too Yeah Yeah, if you wanted to do that if you wanted to have your database.yaml file or something in a second repository and then pull it in and do the replacement on your current tree just say replace that you have to put a database that yaml file that you know the shaw that doesn't doesn't change and then just say replace the shaw with the shaw, right? But then if the database changed you need to change the replacement as well like the config settings but yeah anything you do blogs in this case we'll replace the commit so we push the history up to some second server and then what we want to do is split our repository, right? so what we did there was we basically pushed just the last four to one repository so now we need to separate our repository so what we do is we say we put I think one of the best ways to do this is put instructions in a file it says here's how to get the rest of the history and graph it on here so that if you run a log or something or a blank and you get to this commit what you do is you set up a base commit that says you've reached the end of the history here's how to get more, right? and so you set up your file that does that you run this command this says give me a commit that has the same tree as the last commit that I want to be in my working history and give it that commit message instead, right? and so it gives you a commit shot so what that does is just write a commit into your database that doesn't have anything pointing to it that the message is the instructions on how to get more data and then what you want to do is rebase everything upstream from that on top of that instead so that's her end point, right? so if you rebase it'll apply all the commits on top of that so you now sort of move all the commits over to that that base useless instructions base one, right? and so now you have a little short history and that's your new history and you force push that up to wherever people are cloning from and now when people clone they just get this little tiny history of four and five and that's it, right? and then at the end there's instructions that say here's how to get the rest if you want it and the way that they do that if they do that is they say so they say clone your project they look at it it only has a couple of commits in it and the last one says here's how to get the history then they follow those instructions by saying okay add a remote call history and pull from that and that will give me the rest of the history and then I can simply so there's the master branch in the history server and then you graph them together, right? so if you say replace replace that fourth commit there 8.1.a.7 with the last commit in the history version then when you say get logged everything's graphed together, right? you get one long history instead so this is a fairly nice way of being able to split up the history the one extra line I believe is thinking about doing this because it's starting to get big enough where they just want one history with like the last year and then the previous four years can be graphed on if you really want it when they push what? the push is still going to be the last commit is e14 so any new commits you create will have that parent and so it's not going to be any different yeah it won't work it depends, right? because it depends on all you're saying is take any time you see this commit and pretend it's this other one if it's reachable whatever branch that commit is reachable for it will replace them in all of them then it will look like they merged in and then had two different bases yes you can replace any object and get with any other object as many times as you want okay so now we've graphed this stuff on and so that's how you do that it's interesting that it goes all the way down to the lowest levels of this so if you say get cat file on a Shaw it will give you that commit, right? and if you say no replace references cat file then it will not replace them so this is actually that 8.1a this is actually the contents this is the contents of the one we replaced it with even though we asked for the same Shaw both times it gave us different you can see that the parent is actually different in these two objects so it doesn't now the contents don't actually match what the check sum is because we're saying at the lowest level replace this object with this object it works all the way down to cat file which is a plumbing command and you can use that no replace references and get in any time to say just ignore all of the replacements that I have if you really want to go back the other cool thing is that it keeps the replacement data in the ref's name space so you can push them and you can fetch them, right? just like you can do nodes or something you can push them and fetch them which means you can transfer them unlike the graph stuff has anybody ever used graphs? unlike the graph stuff which you had to basically copy the file and email it to somebody you can actually push and fetch these so it's fairly nice the other difference between graphs was this you put a file there and you would echo replace this commit with this commit the main difference is that the replacements are easier to share because they are in the ref's space so you can push them they're easier to ignore because you can say no replace references and you can replace any object whereas the graphs would only do commit objects these ones you can replace the trees some interesting things that I've heard people try to do with it is like put in an empty subdirectory instead of a vendor or something and then like if it has a bunch of binary files or something in it and then clone down the binary files and replace the big files with the or replace the sort of temporary files with the big files things like that but then you might come up with interesting things you can replace any object so there's a lot of stuff you can do with it Erlang does this so the Erlang project if you clone it from GitHub you'll only get the last couple of releases not the entire history of Erlang if you want the history you can read that wiki and it tells you how it actually tells you to use the graphs but you can use the replacement mechanism just as easily okay reuse recorded resolution so I'm going to go over this real fast basically the gist of this this particular section is run that because you don't actually need to know anything else that I'm talking about re-read but turn that on because it doesn't hurt anything and it may help you a lot invisibly but what it actually does is let's say that we have a merge conflict we have this file in one branch we internationalize half in the other branch we internationalize different half and then we try and merge them together right so when we merge them we're going to get a merge conflict because we change the same line in two different branches if we forget about that if we edit it to be Olamundo instead right so one was Ola one was Mundo now it's Olamundo and we add it and we want to re-read it it'll tell us that it is remembered how we resolved that problem right it's like when I see Olamundo on one side or Ola World on one side and Ola Mundo on the other I'm sorry Ola Mundo on one side and Ola cheese okay when I see these two things this is how you save them right it remembers that and it says I recorded this resolution so that the next time it sees that if you try and redo this merge it will remember how you solved right and it's very easy to turn this on and keep it have it do that and even ignore it if you want to but it's best to turn it on and you might as well have it remember what your hard work is if we reset and then check out and decide to re-base instead of merging right so we undo our merge and then decide to re-base the change instead what happens is you can see this this conflict and then this line resolve using previous resolution so it sees it says I see that you've already resolved this so I'm just going to redo it for you right so that's one of the really useful things about this if you have a branch that you are continuously re-basing upstream and you don't want to solve the same problems or the same conflicts every single time you want to keep your branch continuously re-base you can use this to do that for you very easily so that when you do the re-base again you don't have to solve the same problems again so now if we look at that the file is solved it'll show us how it did it but this is the other cool thing you can use this in any other context as well it doesn't have to be with re-re-re you can say check out dash dash conflict merge hello dot rb it will read it will put the conflict markers back in right so if you have resolved it it won't get add and then want to undo it and try to resolve it again you can run this and it will sort of give you the merge conflict markers again and then you can say re-re-re-re and it says okay I solved it again that was easy okay so if you wanted to auto-update rather than stopping to make you verify that what it did was okay you could just say merge re-re-auto-update it will just just if it can figure out everything for you it will not even stop and have you verify the merge okay finally I think I have a couple minutes left scripting there's some useful things for scripting git right so if you were writing custom stuff you want to do these super custom things custom workflows hooks all of these things are really useful for writing hooks on the server side something like that there's some useful things to know about what it does one is environment variables so you can move around your pieces of git there are three main ones your git directory your index file and your working directory and these three things do not have to be all together by default the git directory is .git in your project and the index is .git slash index and your working directory is whatever it finds the .git directory but you can move them they can all be in different places if you want to so if you export .gitdir as an environment variable we can move our .git directory out of our repository put it somewhere else in the file system and then either tell git to look there for it and that will work or we can export this environment variable and every time we run a git command it will look for the git repository outside of the tree right so that actually can be fairly useful the index file our staging area the index the way that we when you're going to get add stages of content that goes into a file you can have several of them you can actually have multiple staging areas if you want to and you can tell git where it is with this git index file so if we have two files that are modified and we stage one of them and we look at it now the git gloves are staged and readme is not right if we export an index file we have to initialize it with retreat that reads the last commit into the index and then we add readme instead of git gloves and we run git status now readme stage and git gloves is not right and then we can switch our index un-set the index file which switches it back and look at the status and now git gloves and stage readme is not so we can actually switch back between different staging areas if we want to which is kind of cool I think how do we go back and switch it back and help you do interesting things with that right work tree as well we don't actually have to be in the directory that we're running git commands in we can say here's our status we can export our git directory as the local git directory we can export our work tree as the current working directory and then we can go anywhere in the file system and run git commands and it runs it out of that directory right we don't actually have to be in there so any of those major pieces of git you can say overwriting your credentials you can set these every time you do a commit it will set your username and email as whatever those environment variables are set to that's very helpful for doing pair programming type stuff where you need to change it up and finally Ribbit and lookit2 so Rick did a talk earlier on git that he mentioned Ribbit at the end and I heard a couple people ask about it and this is something that we're doing recently so you can see re-implementation of the git internals the git primitives because the git itself produces a .a file like the library but it is not re-entered so every time that it hits basically any problem at all it calls .a .a is probably its favorite command actually it really really likes .a it calls it everywhere and it makes it a pain there's no public api so you have to go directly into whatever the rest of git is calling it's not going to use the git but it's it's it's not going to go it's not going to use the git but it's it's a lot of you can find a and after the Google so we just paid what You can do a lot of stuff, so Rick was showing this before. It doesn't have like a repo.log, what it does is it gives you a revision walker and you say here are all the heads that I want you to start at. Now just keep giving me the next one you can find until you get to the end. And so it's a walker, right, and you can give it different strategies and stuff. And it's fairly fast because it doesn't do the fork exact overhead. So if you have a huge one-on-one time it's about the same because all you have is the fork exact overhead difference between grit, which most people are probably using if they want to script git and ruby. But if you do it a whole bunch of times, less walking a whole bunch of times, it's way, way faster because it completely skips the fork exact overhead, right? So the more times you do it the better time savings that you get, right? Revision walker API looks like that, it's really easy. You can do raw reads and writes fairly easily. You have to pack files or loose objects, it works fine on both. And it just gives you a nice, you can say look up any shot, gives you an object, and it gives you assessors and centers for all of these things. And I think you can reset, like you can say, I want to commit based on this one, set a whole bunch of the variables and then say dot write, and it gives you a new commit object or tree object or whatever. It has a tree walker, it has an index walker, and all of these are native speed. They run as fast as git does. There's a whole bunch of stuff to it, low-level object API, high-level object API, and Ruby bindings to all of them. So it also has other language bindings. So I started, has anybody ever written Erlang Neef? Neef? Okay, Tom dealing with that, that was funny. It is a sort of, I mean it's an extension in Erlang, right? So you can write, you can run native C in Erlang. So there's an Erlang thing that has sort of started, it's not very usable yet. There is a fairly full Python one though as well. So Ruby and Python, you can do most of the stuff that you can do again in either of those native languages and run it in native speed. So that's it. Thank you very much. Does autoset merge make tracking branches more sane? What? Autoset up merge. Autoset up merge? Is that a big option? Yeah. I don't know, I don't know what it is. That's the first time I've ever been stumped at a git question. Yeah, well done sir. Whiskey for you. Yeah, link to the web. Bitly classic it. Yeah, I'm looking at that git, and I don't see anything about the whiskey thing. About the whiskey thing? Fair enough, I'll amend it. With what? In Lincoln? Not yet. That's very short on our, that's on our short list though. In fact, if anybody has, if anybody is thinking about writing something that wants, that are interested in using Libgit, I don't know what percentage of the audience, how many people might be interested in using Libgit at some point? Oh, okay. So if you have feedback on it, basically what's happening is, I'm defining the API, and then, by the way, it's just working on it in the order that I put down for them. So if you have any suggestions or things you want to do with it or something, go to github.com slash Libgit 2, slash Libgit, or Libgit 2 slash Ribbit, probably the Ribbit library is probably the best place to say, these are some of the things I'd like to do with it, and then we can put it in the queue. Yeah. You're amazing, sir. Yeah, I'm doing training in DC, December 4th, if anybody's interested in person git training as well. And that's an online in December as well. What's the Jumpstart Labs? You can just do Jumpstart. Yeah. So first, a comment that I've been listening to. Yeah, I know. Bye. It's a subversion, and so Git SVN is very helpful, but I didn't read the docs. I hadn't used it in a while, so I basically did an SVN check out, created, did a git knit, which I shouldn't have done. I should have used Git SVN to create those things from the beginning. So I had to kind of manually reconstruct stuff, get it back after I had done the right thing. It looks like the bundles might have helped. Possibly. I mean, if you're using SVN, there's not a whole lot that can help 100%. Yeah, I'm not talking about getting over that start-up problem. We're basically a creator. I've done a bunch of git commits, and I said, OK, now I need to commit it to SVN, and that's when I realized I had done the initialization long. I should have done a git SVN. Yeah, I mean, the bundles are generally most useful when you just don't have a network protocol to deal with. So I use it a lot when I go in and do private trainings at companies or something. They won't let my laptop on their VPN, and we need to share something. That happens all the time. Any time you're somewhere where you can't access the network and you need to get somebody to get stuff, USB keying, the bundles make it very easy to do that. But I don't worry about permissions or anything. Anybody else? All right, thanks.