1. 15

Flight rules are a guide for astronauts (now, programmers using git) about what to do when things go wrong.

  1.  

  2. 4

    I think this is pretty neat. It also raises an interesting pedagogical question, which is when you should show this to someone if they’re learning git for the first time. I think that this is probably one of the last things you should show someone who is new to git, and that it’s important to understand what all of these things are going to do semantically before you hand someone a cheat sheet. I tried to learn git via cheat sheet style, and I had a terrible time of it until I went and actually understood what was going on.

    Now, I use cheat sheets for reminding me of the syntax, and make sure I understand how it’s going to rearrange my DAG before ever actually running any commands. Things are better now.

    1. 2

      I think showing this early would be helpful, because it shows a string of commands used in sequence. This is more useful for someone trying to get done than individually-described commands in the man pages.

      The importance of understanding what the commands actually do goes without saying. When I was learning git, I would create some temporary fake repos to reconstruct a given situation and then would run different commands until I knew how they worked.

      1. 4

        I think showing this early would be helpful, because it shows a string of commands used in sequence.

        I wouldn’t show this to anyone since it advises using git push -f to rewrite remote history. That’s a great way to break other people’s branches, lose other people’s commits, etc.

      2. 1

        Not that it’s directly comparable pedagogically but…

        Maybe somebody could find out when they’re introduced to pilots / astronauts?

        1. 2

          At least for pilots, these are generally called “checklists” instead of “flight rules”. They are different for each aircraft also, for instance, a lightplane’s checklists may only take up a few pages since they are so simple, but an airliner’s may be up to 500 pages.

          Checklists are also not just for takeoff and landing, an airliner has checklists for everything from a broken gear light to an engine failure.

          Checklists are introduced to pilots as soon as they leave ground school and begin training in the plane itself. When flying you always use checklists to ensure that you did not forget something, especially in an emergency. They also help the pilot in deciding what to do, for instance, it would say whether to lower the gear or try a belly landing for each different landing surface.

          Not sure if it really relates to git though, since we as programmers are rarely in a situation where a checklist could be the difference between life and death.

      3. 4

        Note that, as with rebasing (see below), amending replaces the old commit with a new one, so you must force push (-f) your changes if you have already pushed the pre-amended commit to your remote. Be careful when you do this – always make sure you specify a branch!

        You really should avoid changing history on remote repos. It can break other peoples' branches, automated tests, etc. I always tell people not to use it at all to prevent them from developing a bad habit that will cause issues later. It’s much better to review your changes before pushing to make sure everything is in order and rebase if it isn’t.

        There were conflicts

        I’m surprised there’s no mention of git mergetool in this section.

        When I try to push, I get an error message:

        Ugh. See above. If you don’t feel very dirty using git push -f then you’ve picked up a bad habit.

        I made several commits on a single branch that should be on different branches

        I don’t think his approach here is ideal. He’s doing a git reset --hard $sha, then making new branches and cherry picking. If you didn’t make a note of the shas for the commits before doing the reset it’s pretty annoying to find those again.

        Normally I do:

        git checkout -b newbranch $sha
        git cherry-pick $commit1
        git checkout -b newbranch2 $sha
        git cherry-pick $commit2
        git checkout master
        git reset --hard $sha
        
        1. 4

          To be fair, the OP explicitly says that these are “rules for when things go wrong.” If you find yourself in a position where you have to change public history, then something has gone wrong. This doesn’t mean you shouldn’t need to know how to fix it.

          Perhaps the OP should have put this in big giant letters as a warning.

          (To be clear, your advice is spot on. Upvote. I just think it’s framed in such a way that it ignored the context of the OP.)

          1. 1

            OP explicitly says that these are “rules for when things go wrong.”

            He does at the top of the page, but then follows up with examples which you should never do:

            • Amend commit
            • git push -f to fix the remote with the amended commit

            and

            • git rebase -i ...
            • git push -f to fix the remote with rebased branch

            These aren’t situations where things are broken and you need to fix them. They are situations where you are using git improperly and then bypassing git’s checks to prevent you from doing those things.

            In the first example, you should just push the change as a new commit. In the latter example, you should not be using git rebase -i on commits that are already pushed to a remote.

            Git provides tools for merging branches while fixing the history. The advice is really wrong.

            (To be clear, your advice is spot on. Upvote. I just think it’s framed in such a way that it ignored the context of the OP.)

            I hope you don’t take my comments as rude; I just think OP is totally wrong in this regard.

            1. 3

              Yes, when you’re force pushing, something has gone wrong. That is the point. However, this does not mean one is using git improperly. For example, one might accidentally push information that should be private to a public repo. Technically, this information is now public and there is nothing you can do about it. Nevertheless, it would be reasonable to value removing that information from your public history at the expense of force pushing.

              Moreover, there are cases when force pushing is completely reasonable and proper. Have you ever worked on a pull request via GitHub? A PR is technically public, but force pushing to it (say to squash the commits) is not considered poor etiquette.

              You are advocating proper use of git. This is a good thing. However, this does not mean there are never good reasons for using it improperly. (I notice that you subtley moved the goalposts on me. I said, “things have gone wrong when you find yourself having to modify public history.” You basically responded by telling me that my problem doesn’t exist by telling me not to modify public history!)

              1. 1

                (I notice that you subtley moved the goalposts on me. I said, “things have gone wrong when you find yourself having to modify public history.” You basically responded by telling me that my problem doesn’t exist by telling me not to modify public history!)

                I’m not trying to move the goalpost. I just conflated two ideas I had.

                • I don’t think OP’s “issues” need to be or should be solved with git push -f
                • OP’s “issues” are only issues because they have the mistaken idea that changing git’s history and then overwriting a remote with that is a reasonable approach. I’ve yet to run into an actually good reason to need to change a remote’s history.

                Take the example of accidentally pushing a password to your repo, here’s the list of things you shouldn’t have done:

                • Hardcoded a password
                • Committed a password
                • Pushed a change with a committed password

                But, accidents do happen, so how do you fix it?

                • Change the password
                • Commit a change which removes the password from the file
                • Push that change

                Doing a rebase or amend and a git push -f doesn’t offer much, if any, advantage (except to protect your pride, I guess?). It does have the potential of causing more issues, however:

                • Anyone who pulled before the overwrite is going to have issues merging later changes into their branches or their own changes back into the modified branch
                • Rewriting the history doesn’t guarantee someone else didn’t get a copy of that commit and pushed it to another repo (and you may not even think to check)
                • You still need to change that password everywhere ASAP
                • You may overwrite someone else’s changes that came after yours

                So maybe, if you caught it quickly enough, you can remove it from the history before any other copies are made, but I expect most of the time people don’t notice until much later that something like this has happened. Modifying history at that point is really awful.

                Moreover, there are cases when force pushing is completely reasonable and proper. Have you ever worked on a pull request via GitHub? A PR is technically public, but force pushing to it (say to squash the commits) is not considered poor etiquette.

                I have. I have also used git push -f to do just that several times. I have since concluded that is not a particularly good thing to do for several reasons:

                • It caused confusion when the project maintainer attempted to merge my PR immediately after I had changed the history of the PR (he didn’t see what he thought he should in git log after the fact)
                • It caused our automated tests to fall for nonobvious reasons if done after they were triggered but before they had checked out the changes (arguably an issue with our automated test error handling)
                • Needing to do this was generally due to my not having adequately reviewed my changes before pushing them
                • All instances where I did it could have been fixed by making an additional commit instead of modifying the history
                • Github PR comment history becomes nonsensical after repeated review + rebases

                Additionally, it’s possible for the person merging the PR to fix the history themselves if they think it appropriate. (This is done by getting the patch from github directly, applying it, then modifying it as you please, then pushing those changes.)

                The only time I think it really makes sense to do this is for PRs that take a long time to get merged and you need to rebase on newer changes for some reason. I feel like this is generally a bad workflow, but it can happen. I think this is also less of an issue if you’re doing git via email instead of github, as you can just submit a new version of the patch that has been rebased and not have to worry about history.

                1. 1

                  Take the example of accidentally pushing a password to your repo, here’s the list of things you shouldn’t have done: … Doing a rebase or amend and a git push -f doesn’t offer much, if any, advantage (except to protect your pride, I guess?)

                  Umm. I didn’t say password. I said data that should not be public.

                  If that data were passwords, then your solution is absolutely the correct one and it is precisely what I would have done.

                  But passwords aren’t the only type of private data.

                  You can’t just cite a single example, propose a solution, and then generalize this to “overwriting public history is therefore always wrong.”

                  It does have the potential of causing more issues, however:

                  I absolutely agree that all of those issues are very real problems. Nevertheless, there can still be situations where overwriting public history is worth the cost.

                  So maybe, if you caught it quickly enough, you can remove it from the history before any other copies are made, but I expect most of the time people don’t notice until much later that something like this has happened. Modifying history at that point is really awful.

                  Yes I agree it is really awful.

                  I’m speaking from experience here. Someone else caught my mistake a day after I made it. While the data was now effectively public, it would be better to remove it. So I sent mail to the people I work with, apologized about the force push and explained that they should be aware of it.

                  It’s a nuisance of a thing to go through, but that seems like the point of the OP. Something had gone horribly wrong by mistake, and a force push was really the only way to fix the problem.

                  The only time I think it really makes sense to do this is for PRs that take a long time to get merged and you need to rebase on newer changes for some reason. I feel like this is generally a bad workflow, but it can happen.

                  It works well for Rust, and this situation is pretty common in a project that big and moving that rapidly. But yes, I agree with all of the issues you cited. Some of them aren’t related to git and are a result of a crappy GitHub interface. (I have a bookmarklet in my browser that automatically expands comments on “outdated diffs.”)

                  1. 1

                    and are a result of a crappy GitHub interface

                    It is quite annoying at times.

                    Some of them aren’t related to git

                    I really would like to work on a project where patches were done more like the Linux kernel some time. I feel like a lot of engineers use github as a crutch. =/

                    I’m speaking from experience here. Someone else caught my mistake a day after I made it. While the data was now effectively public, it would be better to remove it. … It’s a nuisance of a thing to go through, but that seems like the point of the OP. Something had gone horribly wrong by mistake, and a force push was really the only way to fix the problem.

                    My main point is that when things like this happen it’s a process problem. It’s taken me a couple days to figure out how to put my general idea into words that I think are satisfactory, so I’m sorry for any confusion.

                    My current job does this decently. If you use our standardized workflow all changes get reviewed and must be approved before they are pushed to a remote. Everyone is strongly discouraged from not following that workflow. It has worked well for preventing things that shouldn’t be in a non-local repo from getting pushed.

                    If I were starting from scratch, though, I would want a system where changes are pushed to one remote, then after approval they are pushed to the real “master” remote. Approval would be granted in a multi-stage process: passing any build, passing automated tests, someone signed off on the changes. The main part of this system that I’m unsure of is whether or not to automatically squash the changes. Squashing would prevent data leaking through changes that are added in one commit and removed in another, but you can also lose valuable history for tools like git blame.

                    You can’t just cite a single example, propose a solution, and then generalize this to “overwriting public history is therefore always wrong.”

                    After everything above, I’m not trying to argue “overwriting public history is always wrong” so much as “if you reach the point where you need to overwrite public history then there’s something very wrong with how you’re managing your repo.” The reasoning for the latter is the former, and that’s why I still think the advice in OP is wrong. Yes, it’s good to know how to solve issues like these, but I think we should focus on how to prevent these (and other) issues rather than how to fix them if they happen.

                    What I see a lot of people reading when they see the linked page is “oh, so this is how I can stop having to deal with git’s persnicketiness” rather than treating it as what OP really meant it to be.

                    1. 1

                      I think we’ll just have to agree to disagree here. I don’t think it’s reasonable to assume that we’re all in a position where there is time for careful enough review of every commit to make sure things that shouldn’t be public don’t become public. Overwriting public history is a trade off. If you have enough capital to implement processes that always avoid being in that situation, then that’s great. But if you don’t, I think it’s entirely reasonable to cope with a force push rarely. (And I don’t think there is anything “very wrong” with that.)

                      And certainly, part of this trade off are the number of users of your repository. If it’s very small, the worst case scenario of a force push is a groan from your fellow engineer from across the room.

                      For what it’s worth, aside from that GitHub quirk of hiding outdated diffs, I very much like working with it. I’ve had tons and tons of people contribute to my projects that otherwise probably wouldn’t have. (I don’t want to exclude contributions from people who don’t know how to use git efficiently. GitHub will hand-hold novices, and I like that.)

                      1. 1

                        For what it’s worth, aside from that GitHub quirk of hiding outdated diffs, I very much like working with it. I’ve had tons and tons of people contribute to my projects that otherwise probably wouldn’t have. (I don’t want to exclude contributions from people who don’t know how to use git efficiently. GitHub will hand-hold novices, and I like that.)

                        Oh, don’t get me wrong, I do like github and think it has helped collaboration on a lot of projects. I don’t think it’s the best thing to use if you want to keep your repos private, however. Especially if you already are using other tools for issue tracking, etc.

          2. 2

            “He” should be “she”. Not a big deal in general, but let’s make sure not to assume that neat new projects are done exclusively by men.

            1. 1

              In english, “he” is used when the gender of the subject is unknown. Also, using “she” would be just as bad, since it assumes that all new projects are done exclusively by women.

              Of course, you could use “it”.

              1. 2

                I don’t think that has been true for at least fifty years. There are plenty of other ways of referring to the author without using a gendered pronoun, like “the author” or “k88hudson”. If you really want to use a gendered pronoun, it’s not a ton of work to go check who the author is, and whether you can guess a gender.

                The pronoun “she” is not just as bad in this case because the author is actually a lady. Using a gendered pronoun appropriately does not insinuate anything.

                1. 1

                  The pronoun “she” is not just as bad in this case because the author is actually a lady. Using a gendered pronoun appropriately does not insinuate anything.

                  Agreed. I didn’t realize that we were talking about a particular person here. Where is this pronoun of contention, exactly? I thought you were talking about the article itself, which was written by k88hudson (I think?).

                  1. 2

                    Maybe it would be useful to add a “parent” link to comments. The parent of my comment (which you replied to) is here.

                    1. 1

                      Wow, yes, that would be great. I didn’t even know your comment had a parent. Sorry for the misunderstanding. ;-)

                2. 2

                  In english, “he” is used when the gender of the subject is unknown. Also, using “she” would be just as bad, since it assumes that all new projects are done exclusively by women.

                  Historically this may be true, but today, “they” is used fairly commonly as a gender-neutral choice. See also various other alternatives.