List

Git your PR accepted. Rebase your changes like a pro

Git your PR accepted. Rebase your changes like a pro

by Daniel Magliola

In his talk at RailsConf 2022, Daniel Magliola introduces strategies for effectively managing Git pull requests (PRs) using the rebase function to create a clear and coherent commit history. This is particularly useful when contributing to open-source projects where messy commits can complicate the review process. Magliola emphasizes the importance of structuring commits to tell a story, making it easier for reviewers to understand the thought process and changes made during development.

Key points discussed in the video include:
- The Importance of Commit Cleanliness: Large PRs, while sometimes necessary, can deter maintainers if not well-organized. By breaking down commits into manageable, meaningful units, the review process becomes significantly easier.
- Understanding Git Internals: Magliola explains how Git tracks changes through commits and branches, allowing for flexibility in manipulating commits. He highlights that commits are essentially differences (diffs) from the previous state, which can be reapplied in different contexts.
- Using Interactive Rebase: He explains how the interactive rebase functionality allows developers to reorder, squash, and edit commits, which helps in cleaning up commit history. Specific commands like "pick", "drop", "squash", and "fix up" offer fine control over the final structure of the commit history.
- Handling Mistakes During Rebase: Magliola details strategies to recover from common pitfalls in the rebasing process, such as using the git reflog to navigate back to previous commit states or abort the rebase if conflicts arise.
- Commit Messages Matter: The significance of writing clear and informative commit messages is stressed, as they provide context for reviewers and future developers alike.

Magliola concludes with the message that mastering Git and its rebase functionality not only helps in getting PRs accepted but also maintains a cleaner codebase for future contributors. He encourages developers to invest time in mastering these techniques, as they lead to more maintainable code and foster better collaboration in open-source communities.

You want to contribute to an Open Source project, and you have a complex PR to submit. You've tried to keep it small, but sadly getting there took a lot of effort and your branch has more than 30 commits with fixes and reverting of dead ends.

You know reviewing this will be a nightmare for the project maintainers, and more importantly, it will be almost impossible for anyone in the future to understand what you did by looking at the history.

In this talk we will look at how Git branches work, and how to manicure them using Rebase to build a commit history your colleagues will love you for.

RailsConf 2022

00:00:00.900 foreign
00:00:12.540 I would like to tell you about APR this PR this is my first real introduction to
00:00:18.720 open source and it was quite a challenge there was this small gem that we need to use and to make it work we had to
00:00:25.800 practically rewrite all of it that we ended up with was the big boy which is never ideal but this one had to
00:00:32.940 be big because all of the parts had to change together you've probably had to review PS like
00:00:38.399 this and I can see you crying on the inside right now just seeing these numbers but
00:00:43.920 if you did try to reveal this PR it was actually quite easy to follow because you didn't have to read all of the code
00:00:49.020 changes at once the pr was made of many commits each commit did one thing and he explained
00:00:54.960 what that was and why we did it that way on each of the commit messages if you did read these comments one by
00:01:01.500 one you would build up this story that will let you follow what was happening quite easily so even though this was a
00:01:07.860 very big change this made it reviewable and it was actually a huge part of how we managed to get this matched if we
00:01:13.439 hadn't done this we probably would have had to Fork the gym because there's no other way to review a change like this
00:01:19.799 now I don't recommend that you write PS this size this was a bit of an extreme case but even with smaller PRS it's not
00:01:25.920 uncommon that you have to do several different things at once and I do recommend that you clean up your commits
00:01:31.380 so that there is still a story that is easy to follow step by step because the alternative is just leaving
00:01:37.979 the comments as they happen which generally looks like this this is much much harder to review
00:01:43.140 because you can't get any useful information from the steps that we're taking here so your only choice
00:01:49.320 is to read all of the files at once in alphabetical order which is the way that gif has shows them to you
00:01:55.439 now I want you to imagine that you're going to sit with a colleague and explain your changes you will go through
00:02:01.020 the files alphabetically right that won't make no sense instead you would explain this like a story with building
00:02:06.119 blocks that depend on each other starting from the basics and building a fuller picture as you go
00:02:11.760 when you submit to an open source project you don't get to sit with the reviewer so you have to do all of that
00:02:17.220 explaining through your commits again starting from the very basic changes explaining why you did those and then
00:02:22.379 building up to the full story over the following commits as if you were sitting down with them
00:02:27.780 and this is not just our reviews by the way bad commits are an even bigger problem for anyone in the future trying
00:02:33.840 to understand why the code is the way it is I found this call the other day for example like that was weird
00:02:41.040 was that intentional is that a bug so I get blamed to see if the commit
00:02:46.260 message would explain how we got here and this is what I found this is
00:02:51.959 this is not helpful what you want is what Eileen showed us yesterday right you see this code you
00:02:57.840 see something that you don't understand you check the commit and there's a perfect explanation of what happened why
00:03:03.480 the code looks the way it does and only that in this one there's even a heads up hey in the future we may need to add
00:03:10.680 more of these I want you to compare this kind of context with this
00:03:17.040 as developers we all put a huge amount of time and effort into making sure that our code is maintainable
00:03:24.000 but when you remember that the code is not the only thing that matters it may not even be the main thing that matters
00:03:29.879 being able to understand how we got here is a huge part of maintaining a system
00:03:36.120 so you want to do this instead and tell a story it will make it the life of your reviewers easier it will make it more
00:03:42.180 likely that your changes will get accepted and it will leave a cleaner trail of changes for posterity
00:03:47.940 now of course I didn't just magically commit all of these in their final perfect shape on the first try this PR
00:03:54.060 was months of work of changing and tweaking and experimenting I must have gone through hundreds of crappy commits
00:04:00.540 but I can't see any of that in the final result the final result is a pristine story without any of these matches of
00:04:06.900 the rewrites and the failed experiments and to do that you'll need to edit your commits you don't want to show the
00:04:13.379 complicated windy path that you took to get to the result you want to clean up your commit so they tell a straight story that is coherent and easy to
00:04:21.060 follow and for that you need interactive relays now rebase
00:04:26.699 is a bit of a weird tool um it has a bad reputation I know several folks that tried
00:04:32.699 replacing once and they got some weird results or lost some code and never tried the racing again they just went straight with merging forever after that
00:04:38.940 because there was good of it and that's fair as usual we get the ux is pretty
00:04:44.520 obscure the error messages are cryptic and scary it feels like if you make a small mistake you can lose your commits
00:04:51.600 in hours and hours of work Louise is genuinely hard to get into at first and the problem is that unless you
00:04:58.380 have a good chunk of background information when you start it's really hard to understand what it's doing and
00:05:03.720 how and so when something goes wrong it feels arbitrary and kind of mean to be honest
00:05:09.180 so let's fix that today we're going to learn how you can do this too well then
00:05:14.220 how everybody's works and how you can make your commits cleaner get your changes accepted and
00:05:20.280 and the and the ammunition of your peer your peers and the Gratitude of anyone who get blames your code in the future
00:05:27.000 first of all though hi my name is Daniel and I work at indeed Flex with a Flexible Staffing platform based in
00:05:32.340 London as you probably noticed I'm not originally from London I come from Argentina so in case you're wondering that's the accent and with that out of
00:05:39.000 the way let's go to racing as I just mentioned when when you want to understand the race it's useful to start with a little bit of background we
00:05:45.660 want to know a little bit about how git Works under the hood because if you know how it works it makes things much easier
00:05:50.880 to understand now I'm going to keep this short there are only three important things that I want you to remember and by the way I'm
00:05:57.360 going to make some simplifications here don't add me I know some of this is not exact but it's a useful way of thinking
00:06:03.600 about how this works as you know as you evolve your code you end up with a series of commits for all
00:06:08.699 of your changes each of these commits lets you see the state of your code at that point in time
00:06:13.979 but the commits don't store the whole state of your code at that time instead each commit depends on the one that came
00:06:19.680 before it which we call the parent and it represents only the changes that we made to files on the apparent this is
00:06:26.819 the diffs that are used to see in it only represents these differences these changes so let's commit here doesn't really have
00:06:33.720 your code at that point in time the code you get if you check this commit out is the result of applying this div to the
00:06:40.560 call in the parent but the interesting thing that is that because each commit only represents these changes they can exist
00:06:47.400 independently of their parent you can move them around so this example for example you you have a separate Branch the code in the blue
00:06:54.479 branch is going to be different from the one in the yellow one but I can totally take that top commit and just copy it over here and whatever it stiff was gets
00:07:01.500 applied to the code in this new parent and in fact if you've ever done a cherry pick that's exactly what it does
00:07:07.560 so important thing to remember number one commits are just a diff and you can apply them to a different parent if you
00:07:12.780 want you can move them around now if we go back to our commits as you probably know git lets you use git
00:07:19.080 checkout to jump to any commits and see what the code was at that point but to do that you need to refer to
00:07:24.599 these commits somehow an instrument has a unique shot that you can use as a handle to refer to it so if you want to
00:07:30.180 check out these commands you can just get check out their shot but that is really inconvenient you don't want to be
00:07:35.400 typing shots all the time so instead git gives us preferences basically we can label these commits to
00:07:42.780 make it easier to refer to them and there are two types of references tags and heads and these are both almost
00:07:48.660 exactly the same thing it's just a convenient name that you can attach to a shot and in fact if you ever look into into
00:07:55.080 the dot get directory where git keeps all its info that's all they are a tiny text file with the shell of the commit
00:08:01.319 that they point to now you shouldn't normally do this but if you create a new text file here and put it the shy of a commit inside you've
00:08:08.460 just created a branch that's all they are now since there are two types of references tags and heads and the
00:08:14.639 difference is that tags just point to a commit and don't do anything else now they're useful as historical markets
00:08:20.940 for something that happened at some point in time we normally use them to keep track of which commit was released
00:08:26.699 in a given version now heads are almost the same but I have a special trick let's say we're going to
00:08:32.580 make a new commit here you normally have some Branch or head checked out and that head is pointing to a commit that's the
00:08:38.940 one we will be diffing against in the new commit we add so a new commit will have this as his parent and when you
00:08:44.459 make that new commit it will not only show up here at the top but the head will also automatically move to point to
00:08:49.620 it now that may sound a bit weird or confusing but this is the usual behavior that you used to every day you're
00:08:55.620 normally on the main branch or in some other branch and that's your head and every time you commit the branch moves
00:09:00.839 forward to point to the new commit you just made and that in a nutshell is all other branches it's just a reference to commit
00:09:07.320 that moves forward when you get new commits that's it and the reason I'm telling you this is that understanding how these heads or
00:09:13.920 branches move is the key to understanding the race so important thing to remember number two branches are just a pointer to a commit and that
00:09:20.459 pointer can move by default they just move forward but you can report them wherever you want whenever you want by
00:09:26.700 doing a gate reset hard for example you can reset this head here and now this is where your main branch
00:09:33.180 is now you'll notice that those two commits at the top have now effectively disappeared they are orphaned now
00:09:39.420 because there's no head pointing to them keep that in mind we'll come back to those later
00:09:45.060 let's talk about merge for a second here we have a very neat linear set of commits every commit has one parent and
00:09:52.019 one child but there's also a number of special cases first of all a commit can have more than
00:09:57.779 one child two commits can have the same parent and this is how we get separate branches right you can have your main
00:10:02.820 branch here in yellow but you can also have another commit that depends on this guy down here and then a bunch of other
00:10:07.920 commits that depend on our and this is basically what happens when you make a future branch and then generally you want to make a PR to match
00:10:14.640 it back to main so one special case is two children the other special cases all comments
00:10:19.920 have a parent but some commits can have two parents which is what happens when you merge a branch into another
00:10:24.980 Merchant look at that into a bit more detail when you merge this Branch into this one Gil will go back and figure out
00:10:31.560 where the branches diverged then it will take all of the changes from all of the commits in the branch since then and it will collapse them
00:10:38.160 into one big diff and apply that diff to the branch you're merging into and that is your match commit if you
00:10:44.579 look at his death is the cumulative changes of all of the commits in the branch and then the target Branch moves to
00:10:51.120 point to that so that's how much work it collapses all the individual diffs into a single one and puts it in a single commit with two
00:10:57.300 parents now let's talk about rebasing finally If instead of merging you rebase onto another Branch people do something
00:11:03.540 similar you will also go back and figure out where the branches diverged it will also take all of the commits in your
00:11:08.700 branch but it won't collapse them into one remember we said earlier you can take a commit and reapply it anywhere when you
00:11:15.420 rebase instead of collapsing your commits it will sorry GID will apply them one by one to
00:11:22.320 the Head your of the branch you're racing against so you still have the same commit history but you also have
00:11:27.480 all the latest scores from the target branch in this case Main and then it will repoint the branch
00:11:33.300 reference to that new head commit that's basically all that rebates does so important thing to remember number
00:11:39.360 three when revising it will apply all of the commits one at a time and then reset the branch head
00:11:46.440 now just like the last reset we did you can see that we have these orphaned commits you don't normally see these
00:11:52.260 because kids command line and graphical clients generally only show your commits that have some sort of reference pointing to them and nothing is pointing
00:11:59.579 to these but they're still there they didn't go away you can still check out any of them and you can also get reset
00:12:05.519 your branch back to them if you want and they will effectively in this case undo the rebase and now these are the orphans
00:12:12.779 now this is going to be key to recover from problems so we're going to talk more about that later
00:12:18.000 that's the main thing to remember here we can easily repoint Branch heads anywhere anytime I'm revising you will
00:12:23.519 do that a lot it's a pretty fundamental tool all right enough of our internals let's talk about what we've all been waiting
00:12:29.760 for let's talk about rebase interactive how you can edit your commits and make your history gloriously clean
00:12:36.600 the reason directive is the exact same thing as rebase it will take all of your commits and you will apply them one by
00:12:42.300 one but you get to interfere in the process you get to change how these commits get applied and this lets you do
00:12:48.600 lots of fun things you can change the order of the commits to present the story more clearly you can add new
00:12:54.000 commits in the middle of that story or if you have a committee that's doing too much you can split it in two or you can
00:12:59.100 take two related commits and actually squash them into one and combining all of these operations is
00:13:04.200 how you're going to create the previous commits anyone has ever seen now let's see how this works here we
00:13:09.600 have a bunch of commits in a branch and we want to rebase them against Main and modify them now these companies are
00:13:14.880 completely made up but I try to make them somewhat similar to what happens when we're developing and well the
00:13:20.279 particular commits don't matter much I want to tell you a bit about them because it will make the next Parts easier to follow
00:13:25.740 in this Branch we're adding a feature after running CI we need to fix a couple of problems we also try to think that
00:13:32.040 didn't work but we kept it in a committing case it was useful later wasn't useful so we actually want to get rid of this
00:13:38.040 this is another fix and when we committed this we went in a Russian we didn't have time to write something decent we need to fix this commit
00:13:43.380 message to add a better explanation we also found some other problems that got in the way in other parts of the
00:13:49.019 code and this shouldn't really be on this branch and in a proper open source submission you should make a separate PR
00:13:56.339 ior but in your own code basically we can just leave it there at least we left in a separate commits
00:14:01.920 and then of course RoboCop complained about stuff so we fixed it to a piece of robot overload
00:14:08.279 so here's what we want to do with these changes to clean them up first we're going to drop that experimental commit
00:14:13.800 then we want to fix this commit message we want to move the unrelated changes so
00:14:19.139 they are first and we're going to combine these two into one so let's see a really quick example of
00:14:24.899 how it always interactive and how you can help us clean this up we start around branch and we do give revised main dash dash interactive this
00:14:31.800 will open up your favorite text editor with a list of all of the community branch and you can see here A bunch of commands on the left
00:14:37.980 as you can see this whole thing is just a bunch of text and the idea here is that we're going to tell git what to do
00:14:44.459 with each of these commands by default it will pick every commit and pick just means apply this commit like we saw
00:14:50.940 earlier but we can also do other things remember this experiment commit we don't need we tell you to drop it
00:14:56.940 the next commit has a crappy commit message so we're going to reward it this one is not related and we want it
00:15:03.360 at the top so we're going to cut this line and paste it up here to change the order in which the commits will get applied
00:15:08.820 and finally these two need to emerge into one so we will squash them then we exit our data saving the file
00:15:15.420 and it would do what we just said it will apply the commits we told it to in the order that we said this is the one we said to squash it's going to let us
00:15:21.899 edit the message and then it's going to skip over the one we dropped and when we reached the one we wanted to reward it'll open the heater again just like
00:15:29.220 when we get commit so we can edit the commit message I know we're done successfully replaced
00:15:35.639 that was a lot and I want to go over what happened in a second but first I need to point out something about the race that I think at the beginning is
00:15:41.820 super confusing when you're looking at git commits either in the command line on a graphical client you always see all
00:15:48.240 commits at the bottom and newer commits at the top but when you replace interactive they
00:15:53.579 show the other way around the first comment you made will be at the top and the latest one at the bottom
00:15:58.860 and this is the same way GitHub shows them to you and it makes sense when you're editing your commits but it does
00:16:04.019 make it harder to follow what's going on when you're switching from editing the commands to looking at the results so keep that in mind
00:16:10.560 so let's look at what has happened in database this was the commits before this is what we all get to do remember it's upside down and this is the result
00:16:18.899 now you can see we got rebased on top of Main but also now the commits are in the shape that we said this is how that
00:16:24.959 happened in order we'll reorder this one to be first we squashed these two we dropped that experiment we rewarded this
00:16:31.920 fix and then we just picked that last one now this is an amazing tool and once you
00:16:37.199 get used to thinking about commits in this way you can take full control of every line of code in every commit it's
00:16:43.380 incredible power but again a lot of a lot just happen really quickly and that was maybe a bit abstract so let's look at these comments
00:16:49.380 in detail and talk about when you should use them first there's reordering now reordering
00:16:55.259 is one of the simplest tools we have but it's super powerful to control The Narrative of your PR the order in which
00:17:00.600 you add your changes can make it much easier or harder to understand what's going on for example it's common to have a few
00:17:07.500 things that are routine cleanups that maybe are a bit unrelated to API but you need them there I like to put those comments at the very beginning so you
00:17:13.740 get them out of the way before we start on the real changes and then they don't break the flow later or if you have a thing that you first
00:17:19.740 refactor so you can make it easy to change later and then you make the easy change you wonder in two separate
00:17:24.780 commits but you also want them together so it's easy to to follow the story
00:17:29.820 and mostly remember reordering is important for other techniques we'll learn for example if you want to squash two commits into one but there's other
00:17:36.480 stuff in the middle you first need to reorder them together and then you can squash them now doing it really easy is not even a
00:17:43.080 revised command you just change the order in which commits get picked by adding the file and cutting and pasting
00:17:48.900 lines around the next command is to actually squash
00:17:54.120 and fix up these are two commands for doing the same thing which is combining several commits into one
00:18:00.059 now the reason there are two commands is the commit message if you squash you will have the message of the second
00:18:05.220 commit onto the first one and you'll be used to seeing this if you use the squash and merge pattern in GitHub
00:18:11.700 fix up instead will discard the second message and it's always the better option I have to say I've been
00:18:17.880 manicuring complete history for years now I have never once used squash because the resulting from a message
00:18:23.039 generally ends up being garbage if you're taking two commits and combining them into one you generally don't care
00:18:28.919 about that second one so you don't want that message and even if you do want parts of it I I do think it's better to
00:18:35.039 fix up always and then at the end look at your actual commit message look at the changes and then reward it to
00:18:41.460 describe exactly what's happening it's gonna make it much more coherent now when you have several commands that
00:18:46.740 you want to turn into one what you do when revising is you will reorder them so they're next to each other leave the first one as pick and you're
00:18:54.000 going to set the other one as either squash or fix up when you finish that erase this will leave you with only one commit with the
00:19:00.179 code of all of them now because we chose squash he will open the text 8 and you can see here the second common message is still there and the third one isn't
00:19:06.900 it's commented out if we had just chosen fix up for both you don't even get the gator which saves you a more time
00:19:14.400 squashing is one of the most useful techniques because there are many situations where we start with separate commits that really should be only one
00:19:21.000 for example you wrote some code then you remember the tests that you were supposed to write so you put them in a
00:19:27.000 separate commit separate doesn't really help tell the story so that's a squashing or you wrote some
00:19:33.660 code and later changed it in a way that doesn't really discern calling out explicitly that's the squashing you took
00:19:39.299 your several tries to get the Test passing that's a squashing you want to be ruthless here every commit that you
00:19:44.640 leave in the end needs to stand up on its own and have something interesting to say if you can't come up with a commit
00:19:49.919 message as particularly insightful does this question all right let's look at reward now this
00:19:56.640 is probably the easiest to understand but again it's super powerful one because a good commit message is probably the best thing you can do for
00:20:01.860 your reviewers and for anyone in the future that's looking at your code it's trivial to Bluetooth we already saw it
00:20:06.900 your Market go made as a reward it will open the textator and you edit the commit message so before you submit your
00:20:12.600 PR actually read your commit messages compare them with the code and if any messages are not perfect descriptions
00:20:18.120 just reword them and I just want to stop we also saw it before drop just gets rid of a comment
00:20:24.900 sometimes we commit things that don't really belong there may be temporary experimental or maybe you move the code to another branch in a separate VR
00:20:30.960 whatever the case if you don't need it just drop it and now we get to the big guns
00:20:36.299 edit is the most misunderstood and the most powerful commanded release the naming however is terrible which
00:20:43.559 makes it really confusing because it sounds like you'll be able to edit the commit directly and you can
00:20:49.620 but it doesn't work like you might expect what I like to think of is I'd like to
00:20:55.260 think of edit as pick and pause when you mark a commit I said it you will apply it and then it will stop and return you
00:21:01.140 to the command line and now you can do whatever you want with those companies that have been applied and when you get
00:21:06.299 rebates continue kid is going to go like sure whatever and then just take it on faith and just leave them as it is
00:21:11.700 continue applying the next comments for example we have these four commits there and we choose to edit the second
00:21:18.000 one it will apply the first two and put us in the command line now you can see here that the first two
00:21:24.240 commits there are already applied and we can now do whatever we want for example let's create a new file
00:21:32.280 add it to git and then make a new commit and then when we rebase continue
00:21:39.780 it's going to continue applying the rest of the commits that we had pending and you will see now in a second that instead of the four commits we started
00:21:45.900 with you now have five we just added a new commit right in the middle so hopefully this gives you an idea of
00:21:51.120 what's Happening we pick the commit pause and you can do whatever you want and the possibilities here are endless
00:21:58.080 of course the easiest thing to do is to actually just edit the committee you chose when git drops you in the command line you can modify some files and git
00:22:04.559 commit amend which is what the rebase message tells you to do and then gitrus continue to
00:22:09.900 apply the rest of the commits now if you actually have a manual element to a Commit This is an option but I find this
00:22:15.120 is actually pretty rare what we very often do is undo the last commit and then reshape it after you say you want
00:22:21.720 to edit a commit you can get reset head up which is going to get rid of the commit but leave the changes in your git status
00:22:28.559 and now you can do anything you want for example let's split that first commit in two after we edit it
00:22:35.280 we can give reset head up which is going to undo the commit but
00:22:40.740 keep the changes you can see here in the get status that we had two files in it let's say those were two separate
00:22:46.140 changes so we're going to commit the two files separately into two individual commits
00:22:52.919 so that's the first commit and that's the second one now you can see now that we have two
00:22:59.820 commits applied instead of the one that we already had and then when we remains continue you will see at the bottom how
00:23:04.860 we have split the first commit in two and now we have all of the pieces to fully understand the magic because the
00:23:10.500 combination of splitting commits reordering them and then squashing is what will give you ultimate power over
00:23:15.600 your community history for one of the most powerful moves the combination of these three actions means
00:23:20.640 you can move code from one commit to another in two rebase steps let's see how these two commits A and B and you
00:23:27.720 can see the bottom one does two things and we would like that top bit of code on the second one to be in commit B
00:23:34.200 no problem first we edit commit a and split it into two and finish that erase
00:23:40.260 and then in another new release we take that new A2 commit we move it after command B and then we mark it as fix up
00:23:48.000 so the two become one and boom we've just moved the code now this is extremely powerful and
00:23:54.120 mastering it is going to make the most difference to your PRS and that's it that's reverse interactive
00:23:59.940 you get to reapply your commits one by one but interfere with how that happens to remold them to whatever shape you
00:24:06.000 need and these are the commands you have to do that now this is a really simple but subtle
00:24:12.059 tool it will let you do pretty much anything you need to do but you need to get used to it and sometimes get a little creative but with some practice
00:24:18.539 you will be making pristine commits in no time now
00:24:23.940 if you ever tried replacing you know that sometimes it can't go wrong so let's talk about how to recover from
00:24:30.480 that because it will go wrong quite often actually but that's okay because we have three easy ways to recover and
00:24:36.240 that's part of the normal process of realizing first of all we have gitre base dashboard if you're in the middle of a
00:24:42.419 rebase and you want to back out you just give away support and give will reset you to where you were before you started
00:24:48.059 your race it doesn't matter how much you've modified so far if the relay still incomplete you can abort and go
00:24:53.220 back to before you start it I use this all of the time mostly when I get surprised
00:25:00.299 when you're revising there are some things that you expect to succeed and there are some things that you expect will give you a conflict so you
00:25:07.440 sort of know because you know your code lots of times there are operations that seem harmless and should complex
00:25:13.140 successfully but all of a sudden they will give you a conflict generally when that happens is because my mental model of the commits and decoding them is
00:25:19.080 wrong so I generally abort and look at them a bit clearly and just take a different approach I also do a lot of
00:25:25.320 experimental racing mostly like I wonder if I could just do this and it will work or it will conflict if it does work
00:25:30.360 awesome if there are conflicts I may back out and then try another way
00:25:35.460 now if you release did finish successfully but for some reason you want to take it back a board is not going to help it's
00:25:42.179 too late for that a super simple technique to recover is to take advantage of GitHub before erasing push
00:25:48.539 your branch then try your relays if you're happy great push again if you're not you should simply reset the heart to
00:25:55.200 the origin branch on your back in business everything that you did after pushing to GitHub is gone and you can now try again
00:26:02.159 another advantage of this technique is that after you rebase sometimes maybe you're not sure whether it went well or
00:26:07.380 not or you may have changed some code that you didn't mean to if you do this you can diff your branch against origin
00:26:13.080 and make sure that despite the changes to the complete structure the code is still the same
00:26:18.779 now sometimes you didn't push to GitHub or you did but then you thought that Rivers had gone well and pushed again
00:26:24.539 and later you find out there was some disaster or something else has gone horribly wrong
00:26:31.380 then it's time for the ultimate time machine now you're not going to use this very
00:26:37.260 often but when you do boy you're going to be happy it's there reflu is one of those tools that are
00:26:42.960 incredibly simple and Incredibly powerful but at first it makes absolutely no sense
00:26:48.539 when you run it it looks like this every time I run it I swear I feel like I'm having a stroke but it's actually really
00:26:54.600 simple we just need to remember two things to understand what's happening first of all as you jump around the repo
00:26:59.640 you're always standing on some commit and wherever you are that's your head you are a commit the head moves with you
00:27:06.539 you check out a branch the head comes along you rebase a branch the head follows you around and every time that
00:27:12.000 head moves git keeps a log of that that's the ref log it's a log of all of the shafts that the
00:27:19.080 head has been in and also what command took it there the other thing to remember is what I
00:27:25.500 mentioned earlier when you rebase the old commits don't go away they're now orphans and you can't see
00:27:31.020 them but they're still there waiting hoping that someday you will love them
00:27:37.679 again and revlog is how you can do that let's look at how this is a reflog
00:27:44.279 output from the sequence that I just showed you we check out main or what main used to be we add a commit we check out a branch and then we rebase the
00:27:51.539 branch and you can see here release that's what I described earlier the first checks are main then picks the commits one by one and then move the
00:27:58.320 branch to the new place now those shots in the terminal are the key to undoing your relays or undoing
00:28:04.380 anything really you just need to find where the way started which can be a bit tricky
00:28:09.480 sometimes because there can be a noise a lot of noise here but if you start from the top you are basically reading your
00:28:14.760 rebase in reverse and then you have where the head was just before starting the release which
00:28:21.600 is here so you just reset hard to that shot and your branch is now back to where it was
00:28:27.840 now of course after resetting hard just like after any relays you will need to then push Force to get up and that's how
00:28:34.320 reflog works and how we can help you recover from all sorts of disasters as a final wrap up I want to repeat this
00:28:41.340 if you're going to remember one thing from this talk is this whenever you're erasing remember that git is applying
00:28:46.919 all of the commits one by one so for example you stop because of a conflict and you need to see how far you got
00:28:54.000 what the current commit is doing that it couldn't apply and think how we apply that commits diff to the code in this
00:29:00.179 current state after in the middle of the release just remember that and you'll be fine
00:29:05.279 um by the way I've talked about the very Basics particularly the internals and I had to make a lot of simplifications and
00:29:10.620 gloss over a lot of stuff but being really good at git is one of
00:29:15.659 the most important skills that you can have as a developer so if you want to learn a bit more about
00:29:22.500 how git Works internally the book pro git has an excellent chapter on all the internals and it's free to read online
00:29:28.200 on that URL it's extremely eye-opening how simple git really is inside and this will give
00:29:34.200 you the mental model to always understand what's happening if you read this book you will get better at it promise
00:29:40.140 and That's all folks I hope you I hope that explanation makes sense hopefully you want to go home try these and become
00:29:46.140 amazing other ways your colleagues and all open source maintainers will thank you for it
00:29:51.240 now before I leave you I do have to mention that I need Flex we're going up growing super fast and we're hiding all over Europe so check this link if you're
00:29:58.440 you know based and I have some stickers here if you like and with that I'll see you in the hallway track thank you
00:30:08.059 thank you