One occasionally hears of some programming zealot who swears up and down that methods should be kept to n lines or less. The actual value may vary, but the arbitrary nature of the claim remains. However, there is a kernel of truth there, and it has to do with preserving unit economy.
We all know that the longer a method is, the more we have to keep in our minds to understand it. There are likely to be more local variables, more conditional statements, more exceptions caught and thrown, and more side-effects of all those lines of code. Furthermore, the problem grows faster and faster as there are more lines of code since they all potentially can have an impact on one another. Keeping methods short has a disproportionately large benefit.
Of course, claiming that there’s some absolute “correct” number is clearly nonsensical. The same number of lines in C, Lisp, Java, Assembler, or Ruby will accomplish radically different things, and even how one legitimately counts lines will change dramatically. What does not change, though, is the need for the reader (and author) of the code to understand it as a whole. To this end, one should strive to keep the number of discrete tasks a method accomplishes to within the range of what people generally can remember at once: between one and six.
Each task within a method may have several lines of code of its own; how many tends to vary widely. Consider the process of reading a series of rows from a database. There may be a task to establish a database connection, another to create the query, another to read the values, and perhaps one more to close everything down. Each of these may be composed of anywhere from one to many lines of code.
Tasks may even have subtasks. Consider the example of building a login dialog. At some point, there is likely to be some code which creates a variety of controls, and places them on the screen (e.g. an image control for the company logo, a text field to capture the user name, etc). In the method which does this, one may consider the process of creating the components a single task which has a number of subtasks: one for each component.
In both cases, the important consideration is how organizing the method into tasks and subtasks helps preserve unit economy. By creating tasks which have strong cohesion (i.e. you can name what that group of code does) and loose coupling (i.e. you can actually separate that group of lines from the others), you give the reader ready-made abstractions within your method. In the first example, the reader can readily tell that there’s a section for setting up the connection, and be able to mentally file that away as one unit without the need to remember each line of code in it. In the latter example, the reader can categorize the series of UI element creation subtasks as a single “build all the UI components” task, and again be able to abstract the entire thing away under a single unit. Even if there are a dozen or more individual components, it still can be considered a single task, that is, a single mental unit.
This ability to create abstractions within a single method is why there is no absolute “right” size for a method. Since grouping like things into tasks and subtasks preserves the reader’s (and author’s) unit economy, it is quite possible to have a method which is very long in absolute terms, and still quite comprehensible. It also implies that a fairly short method can be “too long” if it fails to provide this kind of mental structure. The proper length will always be determined by the amount of units (tasks) which one has to keep in mind, and the complexity of how those tasks are interrelated.
A day or so after publishing Diversity and Justice, I received the following comment from a female acquaintance:
I appreciate you offering this patch! Some code comments from a more senior developer in the area:
Good start with “there are traits which matter and traits which don’t”! Your error is that you’re assuming the only variables that matter are the ones in your Engineering function, but you’re using classes that are defined globally. Banana-gorilla-jungle stuff.
That’s why you’ve got the common misconception “since ‘female’ doesn’t directly come into play in ‘Engineer’, an object descended from both ‘female’ and ‘Engineer’ is the same as an object descended from both ‘male’ and ‘Engineer’.” In fact, because female is a trait that matters globally, anyone in the female Engineer group has had to pass through a filtering function “stand_up_to_assumption_of_incompetence” that requires that engineer be confident in their knowledge, or patient, or stubborn, or lucky, or sociopathic, or possessing some other extra trait; most of which are favorable for Engineering prowess.
If you have two pools of engineers and one is pre-screened, it makes logical sense to exhaust the pre-screened pool before turning to the random pool!
Also, most people who work in this field use a fork of the Justice framework that comes with a bunch of open source tools specifically for working with these filtering functions; like Feminism or Anti-Racism.
Again, thanks for weighing in on the project!
To be honest, my first reaction was to feel annoyed and patronized. I was tempted to ignore the comment and just move along with my day. But I couldn’t, in good conscious, let it go so easily.
First, while my first reaction was to view this as a “negative” comment, I’m not 100% sure that was the intention. I’m perfectly willing to accept a well-reasoned and friendly rebuttal to my ideas. In fact, that’s one of the reasons I publish things publicly, instead of just keeping them to myself. However, I’m a lot less interested in debating a point with someone who is already hostile. But, knowing the person who posted the comment (I attended her wedding!), and being good friends with her husband, I am much more willing to give her the benefit of the doubt as to her intentions.
Second, if you look past the tone of the message to its actual argument, I think there’s validity to her point. That is, any woman who is still in the software field after any length of time has had to put up with a certain amount of bullshit which gives her a certain talent and toughness above the average candidate. That being the case, you could consider female candidates even more attractive than the average male candidate. I think there’s some truth there, and I was even considering various similar ideas when I wrote the original article. But, to keep things concise, I decided to exclude them.
However, the reason I ultimately decided to respond with a new post is because I think this comment actually demonstrates the third part of the trap, as I outlined in my original post:
Finally, it’s a trap for everyone trying to correct the problem. By framing the situation as one group oppressing the other, it creates a powerful “us vs. them” mentality which is hard to overcome. People in the minority group are tempted to identify all people in the majority group as oppressors. Allies in the majority group feel unfairly accused, and are less likely to want to remain allies. Progress in correcting the situation is impeded to no one’s benefit.
Whether it was the commenter’s intention or not, my reaction to the comment was exactly what I described: an ally who was being unfairly attacked. To put it more bluntly, I felt I was effectively being told: “Get out of here; you don’t know what you’re talking about.” with a little pat on the head for at least trying not to be a sexist asshole.
While I wish the comment were more unambiguously friendly in tone, I appreciate the time my acquaintance took to write it, and I think she makes a good point. I would prefer, though, if we all were to follow Lori Lakin Hutcherson’s admirable example when she (a black woman) responded to her friend (a white man) who was struggling with the idea of “white privilege”:
I truly thank you for wanting to understand what you are having a hard time understanding… because I realized many of my friends—especially the white ones—have no idea what I’ve experienced/dealt with…
Lori Lakin Hutcherson
Lori embraced her friend’s attempt to figure things out and be an ally. She was willing to accept his professed good intention (despite his ignorance), and help him understand her own point of view in a friendly, sincere, and very powerfully honest way. I think we should all aspire to follow her example.
I have been thinking about diversity a good deal lately. In fact, at work, I just attended the first meeting of a group to support and promote women in the workplace. I fully support the effort, but it got me thinking… what is the deeper issue here?
At my current employer, we’re trying to build airplanes. That requires considerable diversity: most especially in talent and experience. We need aerodynamicists, structural analysts, inlet designers, electrical engineers, program managers… on and on. We also need people at all levels of experience in their professions. But do we need people with blue eyes? Honestly… does eye color matter when building an airplane? Couldn’t we build a plane without anyone who has blue eyes? What about people with freckles? Do we actually need people to have uteruses? What about dark skin? Do we really need to have a man on staff who’s attracted to other men?
For those first few categories, I can hear you thinking… “Well, I guess not… but, what difference does it make?” But, by the end of that list, I would hope that you were starting to get offended. I think this is the really important point. While it’s likely that you could build an airplane without people having a certain eye color, complexion, gender, race, or sexuality, we should still feel outraged to exclude people based on those traits.
I think the deeper issue here is one of justice. When trying to assemble a group of people for whatever purpose, there are traits which matter and traits which don’t: based upon the purpose at hand. It is manifestly unjust, therefore, to exclude someone based on inessential traits: most especially when they do have the traits necessary for the endeavor.
I think focusing on diversity of race, gender, etc. instead of justice is a trap which bites in three ways.
First, it’s a trap for the company. Imagine a field where 80% of its members are men, and 20% women. Assuming an even distribution of talent, if you were trying to hire the top 10 people in the field, you’d get 8 men, and 2 women. However, if you are obliged to hire 50/50, you’d get 5 men and 2 women from the group of the 10 best people in the field, and then have to hire 3 more women who were not in the top 10. This is clearly not the best outcome for the company.
Second, it’s a trap for the people being hired. First, there are the 3 men who were excluded. It’s unfair, and we definitely sympathize with them. However, it’s the women who actually face the nastier part of the trap. First, the women who were hired won’t know whether they were hired for their talent, or to fill a quota. This is demoralizing all on its own. Even worse, no one else in the company will know either. One can easily imagine the nasty bias and mistreatment which will ensue from people who were already skeptical. With this combination of factors, a reasonable person would feel extremely unwelcome and move along rather quickly.
Finally, it’s a trap for everyone trying to correct the problem. My framing the situation as one group oppressing the other, it creates a powerful “us vs. them” mentality which is hard to overcome. People in the minority group are tempted to identify all people in the majority group as oppressors. Allies in the majority group feel unfairly accused, and are less likely to want to remain allies. Progress in correcting the situation is impeded to no one’s benefit.
I think the better approach is to focus on eliminating injustice: for any group which experiences it, and in whatever form it takes.
This approach requires and supports a great many of the actions one would take with a pro-diversity agenda. Unbalanced representation of women speakers in a conference you’re planning? It is just and pro-diversity to look a little harder to find more qualified speakers who happen to be female. Engineering staff looking a little too white? It is both just and pro-diversity to set up a recruiting trip to universities whose color balance isn’t so pale to hire talented newcomers who might face prejudice elsewhere. Notice though, that it is only just in that you’re selecting people who are qualified through their skills, talents, and accomplishments: not because of some inessential trait. The difference is that you’re putting in the extra effort required to avoid and/or unwind unjust biases against those people to promote justice towards them.
Paradoxically, I think this approach is also more inclusive. Promoting justice is a cause which anyone can support, and for any other person. Instead of creating innumerable “us vs. them” pairings, holding justice as the primary creates only one: those in favor of justice vs those who are not.
Before Object-Oriented programming (OOP), error conditions were commonly reported via a return code, an OS signal, or even by setting a global variable. One of the most useful notions introduced by OOP is that of an ‘exception’ because they drastically reduce the mental load of handling error cases.
In the old style of error handling, any time a function was called which could result in an error, the programmer had to remember to check whether an error occurred. If he forgot, the program would probably fail in some mysterious way at some point later down the line. There was no mechanism built into the language to aid the programmer in managing all the possible error conditions. This often meant that error handling was forgotten.
The situation is much improved with Exceptions, primarily because they offer a fool-proof way to ensure that error handling code is invoked (even if it is code for reporting an unhandled exception). This both makes it unnecessary to remember to check for errors, and it increases the cohesion of such code (i.e. it can be gathered into “catch” blocks instead of mixed in with the logic of the function). Both of these help preserve the unit economy of the author and reader of the code.
Unfortunately, despite being such a useful innovation, exceptions are often abused. We’ve all seen situations where one must catch three different exceptions and do the same thing for each. We’ve all seen situations where only a single exception is thrown no matter what goes wrong, and it doesn’t tell us anything about the problem. Both ends of the spectrum reflect a failure to use exceptions with the end user of the code in mind.
When throwing an exception, one should always keep two questions in mind: “Who is going to catch this?” and “What will they want to do with it?”. With this in mind, here are a number of best practices I’ve seen:
Each library should have a superclass for its exceptions.
Very frequently, users of a library aren’t going to be interested in what specific problem occured within the library; all they’re going to want to know is that the library either did or didn’t do its job. In the latter case, they will want the process of error handling to be as simple as possible. Having all exceptions in the library inherit from the same superclass makes that much easier.
Create a new subclass for each distinct outcome.
Most often, exception subclasses are created for each distinct problem which can arise. This makes a lot of sense to the author, but it usually doesn’t match what the user of the code needs. Instead of creating an exception subclass for each problem, create one for each possible solution. This may mean having exceptions to represent: permanent errors, temporary errors, errors in input, etc. Try to consider what possible users of the component will want to do with the exception, not what the problem originally was.
Remember that exceptions can hold data.
In most languages, exceptions are full-fledged classes, and your subclasses can extend them like any other parent class. This means that you can add your own data to them. Whether it is an error code for the specific problem, the name of the resource which was missing, or a localization key for the error message, including specific data in the exception object itself often is an invaluable means for communicating data which would otherwise be inaccessible from the ‘catch’ block where the exception is handled.
Exceptions should be self-describing in logs.
In most applications, when an exception is finally caught (i.e., not to be re-thrown or wrapped in another exception), it should be logged. The output produced should be as descriptive as possible, including:
For years now, I’ve been following the thread of stories about the overwhelming imbalance of white men in the software industry. Over and over, I’ve seen the questions: “How did this start? Where do we fix it?”. This is the first article I’ve read which makes a serious, well-researched effort to actually answer the question. If, like me, you’ve been concerned about this subject, I highly recommend spending some quality time reading it over.
I’ll take a stab at summarizing some of the high points, but I urge you to go read the full article yourself.
In the early days of computing, the hard part was the hardware. So, that was an area which was pretty strictly segregated along sexist lines. However, writing the software was seen as less challenging, and therefore the process of identifying programmers was mostly done using purely objective measures: usually a battery of tests which determined an applicant’s abilities to solve logic problems. In these tests, men and women tended to score equally well, and so the earliest programmers included a great many women.
In fact, sexism crept in here as well… to favor more women programmers. Since the software part was seen (erroneously) as being largely secretarial in nature (it definitely isn’t), women were often favored for such positions. It wasn’t uncommon to see these massive, room-sized machines tended to by all-female teams of programmers.
This persisted right up to around the personal computer revolution sparked by Apple and IBM in the late 70’s and early 80’s. Before this point, computers were exclusively found at large companies and universities. All students or job applicants hoping to work with them were expected to come in with no experience, and to be taught along the way. This all changed when most families could afford to have a computer in the home.
With computers being commonplace in the home, the gender biases of the typical American family started to play a massive influence over who would eventually become programmers. Young boys would be encouraged to play with the new machines, while girls would be steered toward more typically feminine pursuits. By the late 80’s and early 90’s, this lead to college computer science departments starting to see a huge influx of freshmen who already knew a fair bit about computers: most of them men.
According to the article, this is what started the feedback loop which drove women out of computer science. Overwhelmingly, the students who seemed the most precocious were male, and the professors started to offer preferential treatment to those students. Not surprisingly, this creates a very hostile environment for students starting out the program without any computer experience: largely women.
In the predictable 4–5 years later, the same situation started to play itself out in industry. Programming jobs were increasingly seen as the province of men, and those women talented and brave enough to break into the industry faced an increasingly uphill battle as the balance of men to women continued to shift. Combined with programming increasingly being seen as a challenging intellectual endeavor, the latent sexism already present lead to women being increasingly ignored, trivialized, and passed over. Over the next 10 years, you start to see the alarming figures of 80%–90% men in technical positions at the largest, top-tier companies in the software industry.
What to do?
Even better than merely recounting this dismal history, the article actually talks about some places which are successfully counteracting this trend. In particular, I was impressed with Carnegie Mellon’s approach (which has resulted in 40% of students in the CS department being female). Recognizing the difficulty of new students entering the program without prior programming experience, they’ve started offering different classes to incoming freshmen based upon whether they have prior programming experience. By the time these students have gotten through the first half of the degree, they’ve pretty much all equalled out based upon their own natural talent.
The article talks about a number of other positive steps being taken as well, but not without pointing out that many other problems remain unsolved.
I do not accept guilt by association. So, despite the villains of this piece being male, I do not personally feel guilty to share some coincidental characteristics with them. Instead, I see a group of people who have been treated unfairly for far too long, and I find myself in the position of being able to say something against it. This is not about hating men, nor wanting to coddle women. It’s about hating injustice, and wanting to put a stop to it in whatever form, no matter how similar the perpetrator, or how different the victim.
I am proud to look back to all the women mentioned in this article (and the much larger number who weren’t) as fellow engineers who made my career possible. I appreciate them for it, and I’m glad to pass along word of their accomplishments.
I just found out that one of my parents died last night.
Fortunately, it wasn’t my father. He’s been the one solid backdrop of my life from the moment I was born. For a long stretch between when he divorced when I was 5 and remarried when I was 12, he was the only solid thing in my life. He’s a man of simple virtues, deeply held. He instilled in me, from my earliest memories, a deep and life-long value of honesty, hard work, humor, and family. To this day, I marvel at how he raised two challenging young boys on his own, while dealing with the pain of a messy divorce. He means a great deal to me, and I’d be a wreck right now if I’d just lost him. I’m getting choked up right now even thinking about the possibility. Fortunately, it wasn’t my father.
Fortunately, it wasn’t my mother. I only met her at 11 years old when she and my father started dating. I’m not sure I would have had the courage to jump into a family with two almost feral boys and with a father working two jobs to keep it all together, but she did. She instilled in me a love of culture: fine music, theater, fine dining, cultured manners. She also turned me from a bright, but indifferent student to someone who excelled in school and graduated with multiple honors. On my 18th birthday, we went down to the city hall and adopted each other, and she’s been my mother ever since. I’d be devastated if I’d just lost her. Fortunately, it wasn’t my mother.
It was my father’s first wife, my natural mother. She walked out on our family when I was 5. She was already seeing another man who was heavily into drugs and an alcoholic. Soon after, they married and moved away. My memories of the rare occasions when my brother and I would go stay with them are not pleasant. He was abusive to my mother, and while not abusive to us, still terrifying. She continued the path of drugs and alcoholism as I became an adult, and started my own family. Right around the time my own son was born, I broke off my relationship with her forever.
That was over 15 years ago. I haven’t seen her, or talked to her since. The little bits and pieces I hear though my cousins have made it clear that nothing had changed with her. And, last night, her long-abused body finally gave up.
Am I sad? No, not really. That may seem callous now, but I did my grieving for her as a 5-year-old boy. And, how did I grieve. I didn’t understand who she was, or why she was gone, but my mother—half of my universe of trusted people—was gone. I wished and longed for my parents to be reunited. No matter the shouting and arguments. Eventually, as I grew older and started to understand more, that feeling settled into anger. Finally, as an adult facing those same choices, my feelings changed into disgust.
So, to me, my natural mother died over 30 years ago. I cried. I mourned. And I finished along time ago. Now, I don’t have anything left for the person who didn’t want to be my mother all those years ago.
My real parents are those people who choose to love me. They are the people who gave of their own character to shape mine, and to set me on the best course in life that they could possibly manage. They are the people who have walked the tightrope with me of growing up and striking out on my own. They’ve been with me as I’ve built my career, and as I’ve grown my own family. I literally have tears streaming down my face as I write this: the depth of feeling I have for these two people is so overwhelming.
I regret that my experience with my natural mother has made it difficult to say in person to my real parents what they so richly deserve:
I love you both much more deeply than I could ever express in person, and much more than these written words covey. Thank you for choosing to be my parents.
I recently gave a newly-developed presentation for the first time, and I was concerned that I had too much material to fit everything in. I was going to be giving this presentation at work, and it was supposed to fit in people’s lunch hour, so it was particularly important that I get the timing right. To be sure I got everything to fit, I developed a “presentation timing card” for myself.
To start, I opened a spreadsheet and listed out all the major sections of the presentation. For each one, I went back through my slides for that section and came up with an estimate of how long I thought I’d need to cover each. I wrote that down next to the name of the section.
Next, I used the spreadsheet to sum up all the estimates. No surprise, I was way over the time I actually had. So, I went back through each section, and adjusted the timings to deliberately allocate the number of minutes I actually had across all of them. There was no way to avoid having less time than I thought I’d want to have in each section, but it forced me to make some careful choices about what was really important to cover at what depth.
Now that I had some realistic numbers, I added two more columns to the spreadsheet: the times I should start and stop each section. The first one’s start time was just the beginning of the talk. Each end was just the start time plus the duration I’d assigned. Each subsequent beginning was really just the end of the previous section.
Having finished with the spreadsheet, I printed it out so that it just about fit on a playing card. When I actually gave the presentation, I propped the card up where I could keep at eye on it as I went along. I was surprised and very pleased with how easy it became to hit the right pace for each section. Even with two exercises for the audience and random questions throughout, I was able to finish each of three presentations of the material a few minutes before the end of the session. I will definitely be using this technique again!
This post is part of a Git 201 series on keeping your commit history clean. The series assumes some prior knowledge of Git, so you may want to start here if you’re new to git.
The rebase tool in git is extremely powerful, and therefore also rather dangerous. In fact, I’ve known engineers (usually those new to git) who won’t touch it at all. I hope this will convince you that you really can use it safely, and it’s actually very beneficial.
What is rebase?
To start, I’ll very briefly touch on what a rebase actually is. So, very briefly then, a rebase is a way to rewrite the history of a branch. Let’s assume you’re starting out with a standard working branch from master:
At this point, let’s say you want to update your branch to contain the new commits on master (i.e., D and F), but you don’t want to create a merge commit in the middle of your work. You could rebase instead:
git rebase master
This command will rewrite your current branch as though it had originally been created starting from F (the tip of master). In order to that, though, it will need to re-create each of the commits on your branch (C, E, and G). Remember that a commit is the difference applied to some prior commit. In our example, C is the changes applied to B. E contains changes applied to B, and G contains changes applied to E. Rebasing will be that we need to change things around so that C actually has F as a parent instead of B.
The problem is that git can’t just change C’s parent because there’s no guarantee that the changes represented by C will result in the same codebase when applied to F instead of B. It might be that you’d wind up with some completely different code if you did that. So, git needs to figure out what result C creates, and then figure out what changes to apply to F in order to create the same result. That will yield a completely new commit which we’ll call CC. Since E was based upon C, which has been replaced, git will need to create a new commit using the same process, which we’ll call EE. And, since E has been removed, that means we’ll need to replace G with GG. Once all of the commits have been created, git moves the branch pointer to the end of the newest commit:
While all this seems complicated, it’s all hidden inside of git, and you don’t really have to deal with any of it. In the end, using rebase instead of merge just means changing a single command, and your commit history is simpler because it appears as though you created your branch from the right place all along. If you’d like a much fuller tutorial with loads of depth, I’d recommend you head over here.
Rebasing across repos
If you’re working on a branch which only exists locally, then rebasing is pretty straight-forward to work with. It’s really when you’re working across multiple clones of a repo (e.g., your local clone, and the one up on GitHub) that things become a little more complicated.
Let’s say you’ve been working on a branch for a while, and somewhere along the way, you pushed the branch back to the origin (e.g., GitHub). Later on, though, you decide you want to rebase to pick up some changes from master. That leaves you in the state we see in this diagram:
If you were to pull right now, git would freak out just a bit. Your local version of the branch seems to have three new commits on it (CC, EE, and GG) while it’s missing three others (C, E, and G). Then, when git checks for merge conflicts, there’s all sorts of things which seem to conflict (C conflicts with CC, E conflicts with EE, etc.). It’s a complete mess.
So, the normal thing to do here is to force git to push your local version of the branch back to origin:
git push -f
This is telling git to disregard any weirdness between the local version of the branch and origin’s version of the branch, and just make origin look like your local copy. If you’re the only one making changes to the branch, this works just fine. The origin gets your new branch, and you can move right along. But… what if you aren’t the only one making changes?
Where rebasing goes wrong
Imagine if someone else noticed your branch, and decided to help you out by fixing a bug. They clone the repository, checkout your branch, add a commit, and push. Now the origin has all your changes as well as the bug fix from your friend. Except, in the meantime, you decided to rebase. That would mean you’re in a situation like this:
Now you’re stuck. If you pull in order to get commit H, you’re going to have all sorts of nasty conflicts. However, if you force push your branch back to origin (to avoid the conflicts), you’re going to lose commit H since you’re telling git to disregard the version of the branch on origin. And, if your friend neglected to tell you about the bug fix, you might do exactly that and never even realize.
Solution 1: Communicate
The best way to fix the problem is to avoid it in the first place. Communicate clearly with your teammates that this branch is a working branch, and that they shouldn’t push commits onto it. It’s a good idea for teams to adopt some clear conventions around this to make this kind of mistake hard to make (e.g., any branch stating with a username should only be changed by that user, branches with “shared”, “team” or some other prefix are expected to have multiple contributors).
If you can’t be sure you’re only one working on a branch, the next best thing is, before starting the rebase, talk with anyone who might be working with the branch. Say that you’re going to rebase it, and what they should expect. If anyone speaks up that they’re working on changes to that branch, then you know to hold off.
Once everyone has pushed up any outstanding changes, pull down the latest version of the branch, rebase, and then push everything back up as soon as possible. That looks like this:
If you find yourself having just rebased and only then learn there are upstream changes you’re missing, the simplest way out of this difficulty is to simply ditch your rebase. Go back, and pull down the changes from the origin, and start over (after referring to solution 1). That would look something like this:
This will switch back to master (1), so that you can delete your local copy of the branch (2), and then grab the most recent version from the origin (3). Now, you can re-apply your rebase (4), and then push up the rebased branch before anyone else has a chance to mess things up again (5).
Solution 3: Start a new branch
If you find that you want to rebase right away, and don’t want to wait to coordinate with others who might be sharing your branch, a good plan is to isolate yourself from the potentially shared branch first, and then do your rebase.
git checkout mybranch
git checkout -b mybranch-2
At this point, you’ve got a brand new branch which only exists on your local machine, so no one else could possibly have done anything to it. That means you can go ahead and rebase all you like. When you push the branch back up to origin (e.g., GitHub), it will be the first time that particular branch has been pushed.
Of course, if someone else has added a commit to the old branch, it will still be stuck over there, and not on your new branch. If you want to to get their commit on your new branch, use git’s cherry pick feature:
git cherry-pick <hash>
This will create a new commit on your branch which will have the exact same effect on your branch as it did on the old one. Once you’ve rescued any errant commits, you can delete the old branch and continue from the new one.
I’m hope this makes rebasing less scary, and helps you get a sense of when you’d use it and when not. And, of course, should things go wrong, I hope this gives you a good sense of how to recover.
Two last bits of advice… First, before rebasing, create a new branch from the head of the branch you’re going to rebase. That way, should things go completely wrong, you can just delete the rebased branch, and use your backup. And, finally, if you’re in the middle of a rebase which seems to be going a little nuts, you can always bail out by using:
When studying history, the first rule of intellectual honesty is to never drop the context of the time period being studied. We stand at the end of a long line of people who screwed things up, figured out what went wrong, and came up with a better solution. We are the inheritors of thousands of years learning in every area of human endeavor: including morality. When studying history, any time you indignantly ask the question “How could they?”, it is imperative to stop yourself and ask the question again with curiosity instead. Really… how did it come to pass that people in a prior age thought it right and natural to act in ways we find foreign or even immoral now?
We can (and should) look back with our modern eyes and pass judgement on the moral systems people have used in the past. Most moral codes for most of history were atrocious by our modern moral understanding. However, when judging individual members of those societies, we must not lose our perspective and judge them by standards they never even knew existed. One can only judge a person from a prior historical period by asking whether they faithfully adhered to the best moral code they knew about and/or whether they helped to advance our understanding of morality as such.
This does mean that certain historical figures, though perhaps despicable when judged by our modern standards, where moral and virtuous in their own time. It is important that we judge the moral system, not the person who could have known no better.
Considering Women in History
When thinking of the treatment of women through history (just to pick one minority), we must apply the same respect for context we would for any other historical study. We can (and should) judge historical societies’ moral codes based upon their respect for women. However, we can only judge individual people for having better or worse views and actions compared to others who shared their context.
For example, a person who was skeptical of a woman’s right to vote in England of 1880 is hardly a villain when judged by the moral standards of that time. We now find that position repugnant, but not the person who holds it. Needless to day, a person in a modern context who held such a view would (rightfully) be considered morally bankrupt. Conversely, a person who was enlightened enough, in that place and time, to support women’s suffrage wasn’t merely a normal, decent person (as they would be today), but a one of unusual foresight and virtue.
Notice that I very deliberately used the word “person” throughout that example. We must remember that the suffragettes were themselves usually foresighted and virtuous even among the women of their day. Many women of the time were as skeptical of such things as “votes for women” as their spouses. They too were not villains, but people of ordinary character and understanding: for their own time.
But what about…
The really interesting question is what other moral issues were, at one point, perfectly acceptable, but are not any longer? For example, homophobia was once not only perfectly acceptable, but actively encouraged and legally enforced. However, in the United States today, LGBT+ people are legally protected (in many jurisdictions) and homophobia (in most communities) is actively regarded as backward and immoral. When did that moral stance shift? How did it happen? At what point do you consider someone slow to make the shift as being immoral?
I recently saw the Gillette commercial about toxic masculinity, and it’s gotten me thinking, especially when viewed along side the Egard Watches response video. I highly recommend you go watch both of them before continuing to read here.
The perspectives in both are reflected by the polarized responses I’ve been seeing since the Me Too movement picked up steam. Any time I see such extreme reactions to the same thing (the commercial, especially) among people who normally agree about many things, it makes me stop to ponder what’s going on.
Personally, I find it very easy to have enormous sympathy with the Me Too movement. It is sadly all too easy to find many, many examples of women being treated unjustly in every era, and in every civilization which has ever existed. Indeed, “unjust” hardly begins to describe centuries of disregard, disenfranchisement, oppression, torment, slavery, mutilation, rape, and murder which women have suffered across the span of human history. Given that the perpetrators have been overwhelmingly male, it’s all too easy to take a dim view of masculinity in general.
However, it is also true that many brilliant, talented, moral, and courageous men have moved our species forward in leaps and bounds. Many of these men were the ones who fought against oppressors of every sort (both literally and figuratively). Indeed, many of them fought, specifically, to oppose the tremendous injustice met out to women by other men of their time. Taking either the view that all men are monsters or that all men are innocent is too simplistic.
I view “toxic masculinity” as being what the philosopher, Ayn Rand, called a package deal. That is, a bunch of concepts grouped together with the effect (usually deliberate) of damning the good by linking it with the evil. In this case, the “package” contains a lot of elements which are, in fact, attitudes, beliefs, and cultural norms which each have been held by individual men. However, not all men exhibit all these traits, and, in fact, it’s very common for the negative traits to be concentrated in certain individuals, and positive ones in others.
But let’s get specific here. When I think of traits considered typically “masculine”, I get something like this:
physical traits (size, strength, body shape, genitals)
However, when I think of the kind of behaviors associated with the phrase “toxic masculinity”, I get a very different (and mostly incompatible) list:
sexism & misogyny
excessive use of drugs & alcohol
I think this is the heart of the division I see between people reacting to this issue. When someone says “masculine”, which of these two lists pops up in their head? You can easily tell by the litmus test of these two videos.
What I find especially fascinating and useful, is to construct a similar list using the phrases “feminine” and “toxic femininity”. To my mind, the first list is nearly identical, while the second list has its own (and different) set of revolting behaviors.
My point, really, is that using deliberately leading phrases like “toxic masculinity” or “toxic femininity” doesn’t actually help what is really an admirable goal: to eliminate the specific nasty behaviors associated with those phrases. At best, they serve to stir up animosity and misunderstanding between people who probably have the same goals at heart. At worst, they create a completely useless debate between people wanting to define “masculine” as meaning the first list versus the second.
Instead, I would urge people to discard the “package deal”, and focus on the real problems specifically, and one-by-one: sexual harassment, homophobia, bullying, and all those other behaviors we should no longer tolerate as a rational, civil society.