Category: Long Thought

A longer thought.

Free speech and its many meanings

The last two weeks I’ve been spending way too much time reading, thinking and tweeting about LambdaConf. If you’re unfamiliar with the situation and want to catch up, read this excellent post by @codepaintsleep.

One thing observing the situation has made me realize is that some folks have a very different conception of free speech than I do.

In my mind, our right to “free speech” prohibits the government from restricting or punishing speech. I do not view it as anti-free speech when a group of private citizens denies you the opportunity to speak in their spaces. Nor do I believe our constitutionally protected (in the United States) right to free speech guarantees anyone the right to unfettered expression via commercial platforms such as Twitter, Facebook, etc.

That’s not to say that I don’t have concerns about how companies and commercial bodies regulate expression within their realms. They often do it badly, enabling abuse, or reinforcing existing inequalities. Some entities have sufficient control in how business is done in their industries that their suppression of speech can have adverse affects similar to government censorship.

I also have complicated and unresolved feelings about the use of boycotts. Particularly this is true when it’s a call to boycott a vendor who provides a lot of things to the general public. I think even the most offensive material, should be available for people to learn from, to understand, to be aware of, should they choose to investigate. I think it’s possible in certain contexts to sell something without endorsing it.

Furthermore, I believe that the right to free speech must be balanced with the right to choose with whom we spend our time and what we do with our bodies. This doesn’t make me anti-free speech. This makes me pro-free speech, pro-free association, and pro-bodily autonomy. None of those rights make sense on their own without the others. If your right to free speech means that I have to listen to you no matter what, my right to free association and bodily autonomy is diminished.

Prior to this year’s LambdaConf debate I never thought there was a real debate about this. I’ve been around open source for a while, so I’m familiar with the idea that some think any restriction on speech, regardless of context, is censorship.

What’s new to me is that there are folks who think any mechanism which enables someone not to listen to you violates free speech and is censorship. By this logic, if Twitter were a noisy cafe, then putting on your headphones so you could concentrate would be censorship. And, by this logic, any tool that allow others to reduce their exposure to harassment (blocking, muting, etc.) is censorship. It’s even more egregious censorship if these tools are provided at scale.

Furthermore, some of these folks seem to think ‘free speech’ is an exemption from civil behavior and social norms.

I’m still processing what this means. If nothing else, it helps me understand better what’s going on when we debate about this stuff. Being weary of centralization and government interference is different from being weary of systems which empower individuals to choose what they consume and how they communicate with each other online.

I firmly believe we can create tools and systems which mitigate harassment and abuse while enabling free expression and exchange of information based on choice and autonomy. I believe we can design these systems in a ways that preserve anonymity when desired and that don’t necessarily further government surveillance and intrusion.

But we probably aren’t going to build these systems with the help of folks who are fully committed to prioritizing free speech at the expense of free association and bodily autonomy.

 

 

A product development epiphany

At the beginning of the year, I announced Authentic Engine, my new consultancy.

I’m going to share a rather honest update about how things are going, and I plan to do so with some regularity. This gives me some trepidation. Visibility nearly always makes me feel vulnerable, even if the attention is subjectively positive. And general business wisdom favors secrecy and possessiveness above transparency and sharing. Instead, I’m making a deliberate choice to muster courage to favor intimacy (which requires vulnerability) and community.

Perhaps some of you reading are potential clients or customers and in reading about my uncertainties and missteps you’ll decide not to work with me. I’m okay with that, for if my writing here turns you off then we were never going to be a good match. What’s gained, I believe, will be far greater than whatever’s lost. Some will be enriched reading about my experience. Others will appreciate my candor and that I’m willing to do the scary work of making mistakes, sharing those mistakes, and trying again. Some of you will be motivated to work with me explicitly because of this writing.

So here goes it!

A raison d’etre

While I have a great deal of open source tech experience (my first tech job was in 1997 at UC Davis’ network operations center), I have almost no experience consulting in the way I’ve set out to do now. I’ve worked at start-ups and well-established companies. I’ve started and ran non-profits. I ran my own programming shop under CK Web Development. All those experiences have been immensely valuable, but my experience with them has limited applicability to what I want to build now.

I’ve gravitated towards consulting because I want to apply my experience as a programmer, a technical project manager, a developer advocate / technical evangelist, a non-profit manager, a small business person, and an open source community organizer to help folks working in those fields have better work experiences.

By better work experiences, I mean a few things:

  • authenticity, presence, mindfulness, and empathy in day-to-day work;
  • empowered, adaptive leadership;
  • effective navigation of organizational life; and,
  • the building of meaningful and fulfilling careers without burning out.

This isn’t just about making people feel better at work. Whatever your current role in tech, these are practices which will make you better at your job. The production of software, the governing of open source projects, the evangelizing of technology all requires building and maintaining relationships with people. The better your people skills, the better you can effectively apply your technical skills.

By focusing my work on individuals, I intend to contribute to a cumulative effect of improving our technical and open source communities. The more the folks that make up our communities practice and cultivate the above “people” skills, the more inclusive, sustainable, resilient, and commons-serving they will be.

So that’s my raison d’etre for starting Authentic Engine, but how am I actually going to make a living?

What appeals to me about “consulting”

Before I announced Authentic Engine, I did a lot of reading on what it mean to be a consultant and how to run a consulting practice. Some things I read resonated with me deeply: consulting as a calling, humble inquiry, being a trusted adviser, process consultation and the helping relationship. Other things I couldn’t connect with at all, especially the nature of the marketing and sales processes many consulting business books (such as this one) espouse. I don’t want to have a ton of annoying pop-ups soliciting your email for watered-down content, or resell someone’s proprietary organizational trait assessment. Moreover, many books are scant on details about how to actually develop customers if you don’t already have a base established.

Finally it occurred to me to start thinking in terms of answering the question, “what is my product?” The consulting books say you are your product. Okay, I get that to an extent. But it doesn’t feel very sustainable or scalable to me. Nor does it have the depth of experience I want Authentic Engine to bring to others. I want many teachers, and coaches, and trusted advisers, with all their varied histories, experiences and backgrounds to inform and create what we bring to others.

If I am not my product, what is?

So now that I’ve rejected that I am my product, I have to find out what is. That has me researching and learning all about product development. Working in technology as a programmer, project manager, and developer advocate means that I’ve been on the periphery of product management and development most of my career. Now I’m embracing the role officially, which means learning and practicing a new way of thinking.

I’m in the middle of Steve Blank’s The Four Steps to the Epiphany, which focuses on a kind of lean product development for startups that Blank calls Customer Development. So far the framework is making a lot of sense to me. It centers upon developing a deep understanding of your customer and their needs and using that to inform your product development.

Learning deeply from my customers

So that’s what I’ll be doing next. I’ll be thinking about my customers — starting with folks who hold the jobs I’ve had before: technical evangelists (aka developer advocates) and their managers, software developer and their managers, technical product marketing managers (which I’ve worked for, producing events), and open source project stewards.

Actually I’ll be doing more than just thinking about them. I’ll be reaching out to as many of them–as many of you–as possible to listen and learn what their pain points are, what those pain points are costing them, and how they’d like to solve them. I’ll use this information to validate and improve my hypotheses about the Authentic Engine products that will help them.

Exciting and scary

I’m finding this approach very exciting. I love connecting with people, learning about them, building connections, and figuring out ways . But it’s also terrifying because I know this will take time and our financial reserves are dwindling. While I’m developing my customers and products, I’m also going to have to find income, either through consulting or contracting.

How you can help

So, if you or someone you know is needing help with planning a community-focused technical event (like Open Source Bridge, which I co-chaired for 5 years), or managing a technical project (like creating a localization platform for Firefox OS App developers, which I did at Mozilla), or revitalizing a community contributor platform (like I did with MozillaWiki), or improving open source governance (Stumptown Syndicate), or anything else about which I have subject area expertise, please get in touch or book a meeting.

A promise to continue sharing and connecting

Meanwhile, I’ll keep sharing here what I’m working on and what I’m learning.

Soon I’ll post about:

  • realizing I need to be talking to lots more people and how I’m following through on that despite how weird and shameful it can feel;
  • what I’ve learned about content-based marketing and how I’m putting it into practice;
  • how Sherri and I are figuring how how to support one another and keep our household functional while we both build new businesses;
  • what I’m doing to manage my workload, replenish my “spoons,” and avoid burn-out; and,
  • learning to be okay with uncertainty, imperfection, and iterative improvement.

Keeping in touch

As I intimated above, I promise to make more, better connections with all of you. And I invite you to do the same. Leave a comment below, send me an email, or a tweet, or give me a call (go to authenticengine.com for phone number).

The complex reality of adopting a meaningful code of conduct

A number of prominent, globally distributed open source projects are debating the adoption of a Code of Conduct: Ruby, PHP (rfc, discussion), WordPress. There are probably others. Additionally, thousands of smaller projects have adopted codes of conduct as have many conferences.

Why are some communities able to quickly and effortlessly adopt a code of conduct while others become mired in conflict and division whenever the topic arises?

In this post I explore what I see as the main reasons we experience conflict when talking about adopting codes of conduct in our communities:

  1. misalignment of perceived shared values
  2. the relative difficulty of facilitating organizational change
  3. lack of governance infrastructure and non-technical leadership

What I hope people take away from this post is a greater appreciation for the potential complexities of FOSS communities meaningfully adopting a code of conduct and some ideas for confronting these challenges constructively, including:

  1. closing the non-technical leadership gap in our communities
  2. embracing multiple viewpoints and integrating conflict productively
  3. employing compassion and unconditional positive regard whenever possible

Some Background

Why the current momentum around adopting CoCs?

Many FLOSS communities have been around for years, yet the push for codes of conduct is relatively recent, picking up steam about 5 years ago.

What is the reason for this momentum?

First, let’s examine what a code of conduct is for. The purpose of a code of conduct is to make explicit the agreed upon social norms of group interaction within the community. There are many ways to accomplish this, but generally a code of conduct should document:

  1. expected behavior;
  2. unacceptable (transgressive) behavior,
  3. a mechanism for reporting problematic conduct and grievances, and
  4. consequences for unacceptable behavior.

All communities already have an implicit set of social norms. This is important, so I’m going to repeat: All communities already have a set of norms that govern group interactions, whether they are written or not. What a code of conduct does is make a subset of those norms explicit by putting them in writing where everyone can see them.

Over the last few years there has been a significant push for tech communities to adopt codes of conduct that make explicit a specific set of norms that strive to make these communities more equitable, welcoming, and safer for individuals from groups generally underrepresented in tech. This includes explicitly defining the destructive behavior that those from underrepresented groups are disproportionately subjected to and specifically labeling that behavior as unacceptable. The reason this is important is that the opposite standard of behavior generally remains the status quo across our communities. We may want to believe that harassment and other problematic behavior rooted in racism, classism, homophobia, sexism, transphobia, misogyny, ableism, etc., does not happen in our communities because we have never personally witnessed or been subject to it, but it happens nevertheless.

Making explicit a set of social norms that so clearly strives to re-balance power dynamics is one reason why some have such a vehement reaction against adopting a code of conduct. Those previously in the dominant social group will, on average, have to give up some of their power. Everyone will have to learn new ways of interacting. Change is scary.

Let’s not forget intersectionality

Before I continue, I want to make the intersectionality of my approach clear. Those who generally belong to the group with the dominant social power can suffer abuse and injustice too. Everyone in a community needs to abide by the community norms. Everyone is deserving of compassion and unconditional positive regard. And, many who, because of their relative privilege, are not accustomed to doing so will have to yield power, tolerate some loss, and stretch their emotional muscles further than they have generally been required to do. Some will have to do this while learning how to heal from their own experiences of abuse and injustice.

Two Personal Examples

Case Study 1: Citizen Code of Conduct

We wrote the Citizen Code of Conduct for use at Open Source Bridge in early 2011. We’ve modified it a few times since then and now use it for all Stumptown Syndicate events. Starting with text from a sample conference anti-harassment policy written by members of the Geek Feminism community, we modified and added text as needed to represent and embody the values of our community.  For example, for us, it was important to include not just a list of prohibitions, but also to set positive expectations for community interaction.

We’ve fielded a handful of reports or otherwise acted on our our code of conduct since we adopted it in 2011. None of them matched what I had imagined. Often they were more mundane yet more complicated to respond to than I had anticipated. Adopting our code of conduct did not stir up controversy, though at least one of our responses did. Generally the feedback we’ve received is that our code of conduct makes the conference more welcoming to underrepresented groups and this has been reflected in our changing demographics (more women, more PoC, more queer folks). A small number of people have expressed their discomfort or have stayed away entirely.

We’re a relatively small, contained community. In a given year, about 500-800 people are involved in Syndicate events and we operate almost exclusively in Portland. This has made adopting a code of conduct and responding to it a relatively manageable thing.

But we still have missing stairs. We have a mechanism in place for responding to code of conduct reports, but it’s almost entirely implicit. That works in the short-term, but it’s not scaleable and doesn’t ensure stability and adaptability over time. Communities need ways to transfer critical institutional operating knowledge as new leaders come aboard. Stumptown Syndicate just elected six new board members and Open Source Bridge is looking for new co-chairs, so we’re figuring out how to do this right now.

Another thing that made adopting and responsibly using a code of conduct possible was the reason Stumptown Syndicate was founded in the first place. We created Stumptown to be a trusted holding institution for the open source projects we cared most about. From the beginning we were about providing important governance and other structures that help ensure the long-term health of open source communities.

Case Study 2: Mozilla Participation Guidelines

In late 2012, Mozilla adopted their Participation Guidelines after a months-long and highly contentious process that was kicked off by the Planet Mozilla controversy. I was heavily invested in seeing Mozilla adopt a code of conduct. This cost me a lot emotionally — I got a threat from a co-worker (still employed by Mozilla and now a manager) as well as an anonymous death threat. Looking back it almost certainly burned a good deal of my social capital, too.

I suppose all that would have been worth it if I could say now with confidence that the Participation Guidelines have been useful for improving community interactions and improving diversity and inclusion.

But I can’t. (I would love to hear from you if they’ve been useful to you.)

For the most part, the weird, uncomfortable, blocking, and transgressive behavior I encountered while involved with Mozilla wasn’t (and still isn’t) addressed clearly by the Participation Guidelines. And in the few cases where you’d think the Participation Guidelines would be helpful, they weren’t. One involved a co-worker and was addressed via our employee anti-harassment/discrimination policy through HR channels (to a less than satisfactory end, but that’s another story). The others were from anonymous sources and thus weren’t easily actionable.

What are actionable events according to Mozilla’s participation guidelines are by no means clear to me. What are “exclusionary practices” in this context? The guidelines say

“Intentional efforts to exclude people from Mozilla activities are not acceptable and will be dealt with appropriately.”

But “intentional efforts” aren’t defined or exemplified.

And then the guidelines includes this bit, which to me signals a fundamental misunderstanding of how institutional oppression manifests in individual behavior:

“It’s hard to imagine how one might unintentionally do this, but if this happens we will figure out how to make it not happen again.”

It’s not hard for some of us to imagine how others can unintentionally make spaces unwelcoming because it happens all the time.

Most people who engage in behavior that makes others uncomfortable or otherwise transgresses a social norm do not do so intentionally. And these are the people who benefit most from explicit norm setting and compassionate intervention. The group that engages in transgressive behavior intentionally is much smaller and does so for a varied, complex set of reasons, some of which is more easily addressed by community governance than others.

If the participation guidelines are getting invoked more than I realize, I wonder, by what mechanism are issues being resolved?

Early on the guidelines mention “groups for escalation and dispute resolution” but what are these groups? Later on, the guidelines instruct you to do the following if you experience conflict, you’re to engage with:

  1. the person with whom you have conflict,
  2. other “trusted Mozillians,” or
  3. Conductors.

To my knowledge, Conductors is completely self-selected (no training,  qualifications,  vetting, or standard of conduct) and…mostly defunct. Defunct as in many of the people listed are no longer employees and may or may not even still be involved in Mozilla projects.

Furthermore, the values indicated by the Participation Guidelines conflict with my direct experience of the community and its capacities.

This line would seem to indicate Mozilla values differing perspectives and spending energy to surface and integrate these different perspectives:

“Try to understand different perspectives. Our goal should not be to “win” every disagreement or argument. A more productive goal is to be open to ideas that make our own ideas better. “Winning” is when different perspectives make our work richer and stronger.”

However, Mozilla seems to have no functional, consistent mechanism for doing this. Many times during my four years with Mozilla I saw people who voiced differing perspectives ignored or outright silenced. (Example: Those of us who calmly, clearly, and respectfully voiced concerns about migrating to Gmail were invisibly silenced — our managers were instructed privately to make us stop.)

This line would seem to indicate we value working through conflict respectfully:

“Be respectful. We may not always agree, but disagreement is no excuse for poor manners. We will all experience some frustration now and then, but we don’t allow that frustration to turn into a personal attack. A community where people feel uncomfortable or threatened is not a productive one.”

But we have no effective channels for resolving conflict so we vent publicly and in back-channels, or simply stew in silence.

And how does the value of “respect” as alluded to in Mozilla’s Participation Guidelines apply to the co-worker who proselytizes to people in project spaces without their consent? Or the contributors of religious faith who worry that private demonstrations of their faith could be used to expel them from the project? Or the queer employees who wonder why their company remains silent while nearly every other tech company celebrates the SCOTUS ruling on gay marriage?

Who is getting use from this document? Did the protracted and divisive process the Mozilla community endured to get this document create any lasting, useful change? I don’t know what percentage of the community buys-in to the Participation Guidelines or even knows about them. Does the mere existence of the document make some more comfortable knowing they are there even if they’ve never invoked it?

A comparison to frame the issue

Is adopting a code of conduct like adopting a FOSS license?

Reinventing the wheel bugs me a lot. In tech, I think we waste a lot of resources and make a lot of unnecessary blunders not building upon and learning from what has come before. It’s why we’ve put effort into the Citizen Code of Conduct and making it easy for other communities to adapt and use. It’s why I’m glad others have engaged in similar work, like the Contributor Covenant, the Geek Feminism Wiki sample policy, and others.

Let’s look at a similar activity that should be familiar to a lot of FOSS contributors: licensing.

In the same way that adding a license to your project is “easy” — especially now that Github includes a drop-down selection of them during repository creation — it’s also easy to add a code of conduct.

But how many project owners who have added the GPL, or MIT, or any other open source license actually qualified, capable, and willing to enforce these licenses? And how do they determine, if they’re not well-versed in IP law, which license is really best for their project? Or what the long-term ramifications will be of their selection? Project leads already give a lot of their free time to open source development and community organizing; Do they really have more time to learn the skills required and then respond to licensing questions and concerns? Is that a fair request to make of our technical leaders?

Let’s say a project is five, ten, or fifteen years old by the time someone suggests adopting a license. How is consensus achieved across long-term contributors when some of them are very MIT-leaning and others are very-GPL leaning? Not just that, but when some folks already assumed everyone in the project was pro-GPL and are astounded the topic is even up for discussion.

This analogy has its limits, so I ask you not to over analyze it or take it too far. I don’t think it makes sense to have a third-party body doing code of conduct enforcement, for example. I think enforcement needs to stay within communities. Though I do think we need third-party experts providing training — and there’s a handful of us working on that now.

(Though if you do want to explore the idea of copyleft licensing and codes of conduct further, I suggest reading Sumana Harihareswara‘s excellent essay Codes of conduct and the trade-offs of copyleft.)

The licensing analogy demonstrates two main issues related to meaningful code of conduct adoption:

  1. The complexity of selecting and adopting a code of conduct especially in larger, already established and highly distributed projects/communities.
  2. That code of conduct response requires skills and resources many project leaders don’t already have.

Misalignment of shared values and the painful process of re-alignment

The role of shared values in conflict resolution.

Ultimately, a code of conduct is one part of a community’s conflict resolution strategy.

Making a plan for how to resolve conflict is one of the first things any community needs to do, long before any conflict arises. And it starts with reaching agreement and making explicit what your shared values are. Why? Because the values you agree as a community to prioritize in your work together need to drive decision-making about that work. Do we value unconstrained free expression of speech, or do we value inclusion of underrepresented groups? Do we value “free as in beer” or “free as in freedom”? Do we value shared public resources or do we value private ownership? Do we value adherence to using open source software, or do we value promoting the open web? In cases where are shared values fall somewhere in the middle of two extremes, where do we draw the line and which side is most important?

When communities are young, values alignment is usually implicit. This makes sense. A small number of folks get together to work on a project or advance a particular mission. Often times these folks already know each other. They may know intuitively and from past experience what their shared values are and so they don’t think about spending energy to make them explicit.

If the shared values that were implicit when a community forms are not made explicit as the community grows, you end up with divergent thinking about what the shared community values are. People who where there at the beginning have one thing in mind. People who joined at different points in time think another thing, based on what attracted them to the project and their own experience of interacting with the project/community. It’s really easy to assume the shared values of our FLOSS communities are what we want them to be. Because why else would we be there?

Misalignment of perceived shared values is at the heart of conflict

I see this misalignment of perceived shared values to be at the heart of numerous conflicts in open source communities. I see it pop up in every discussion about whether and which code of conduct to adopt. I saw it over and over again at Mozilla (migrating to Gmail, supporting EME, integrating Pocket, appointing Brendan as CEO, how community is included, etc.). I noticed it each time we struggled with a decision around Open Source Bridge / Stumptown Syndicate, which is why we spent a whole weekend last year debating what our shared principles are and then made them explicit and public.

Adding a code of conduct often requires the painful process of values re-alignment

So, one reason it is so much more complex to add a code of conduct to long-standing projects is because a code of conduct is an operating document born from a community’s shared values and in many of our large open source communities we do not have an agreed upon set of shared values. Adopting a code of conduct is a forcing function that brings that values misalignment out in to the open.

Values re-alignment requires organizational change capacity beyond what we have

To realign on values, a community needs to go through the process of agreeing what its shared values should be (not are — because people have been operating under mixed assumptions) and then put them in writing and make them public. This will inevitably require some change in the community. It’s likely that everyone will have to shift their position at least a bit. If not, some will need to leave the community. The larger and more complex the community, the longer this change process will take and the more facilitation it will require.

Organizational change is extremely difficult and most FOSS communities do not have the capacity and experience to manage the change. For the change to be navigated successfully, great care needs to be applied and community leaders, as well as everyone participating in the discussion really need to step up their game. There needs to be room for anger, for disagreement, for being weary of change, for being ravenously hungry for change. People have to be willing to change their minds. There need to be mechanisms for dealing with the inevitable flood of disruptive outsiders and blocking/sabotaging insiders. Leaders need to be able to hold the environment well enough to drive change but not let their communities implode. Everyone needs to understand and be patient with the reality that the process will take time. Months, not days or weeks.

Adopting a code of conduct in larger communities is not a technical problem with clear, templated solutions. Rather, it is an adaptive one that requires the community learn how to change itself.

The role of governance

Having a code of conduct is part of having a conflict resolution strategy, which is, in turn, essential to good governance.

What do I mean by governance? Governance includes everything about how a project carries out its work and engages with its community.

Key governance questions are:

  • how are decisions made and communicated?
  • how is conflict resolved?
  • how are conflicts of interest handled?
  • who are our leaders, and how are they selected, evaluated, and held accountable?
  • how is community membership decided?
  • how are tasks tracked and delegated?
  • what is our mission, vision and how are we planning to achieve that?
  • what are our values and are we living up to them?
  • what is our reputation within our own community and outside of it?
  • do ensure we have the resources we need to carry out our mission both in the short-term and the long-term?
  • how are we developing our community members and leaders?
  • are we serving our mission or just ourselves?
  • are we in compliance with with local laws? are we up to date on our taxes?
  • are we doing what our community needs us to do?
  • are we hearing all the feedback we need to be? from whom we need to hear it?

Having mechanisms that answer these questions in an explicit, transparent way is key for long-term sustainability and success.

In the same way that shared values are implicit when communities first form, so are the ways in which community members work together. And so must they be made explicit as a community grows. Many communities have not made these governance structures explicit. Or if they have, they are incomplete, out of date or simply don’t match how the community actually operates.

In some situations, generally when communities are small and relatively contained (e.g. to a geographic locality like a conference), it works to start with a code of conduct and make explicit the other governance structures as you go. But that becomes much more difficult the larger and more complex a community becomes.

In the same way that a large community will have misalignment in their perceived shared values, they will also have misalignment about how they think the community works together. Re-aligning is a process that takes time and care.

Does a community need to have all the above questions answered and documented before adopting a code of conduct?

No. But any community, especially large and highly distributed ones need to answer these governance-related questions when figuring out how to meaningfully adopt a code of conduct:

  • Who’s going to be responsible for holding the community accountable to the standards documented in the code of conduct?
  • How will those people be chosen, what training & resources will they need, and by what mechanism will they be held accountable?
  • How will code of conduct reports be collected? Will their resolution be communicated to the larger community? How?
  • What are the legal/privacy/etc. implications of our chosen method of reporting?
  • Have we selected a code of conduct that accurately reflects our community’s shared values, as they are actually practiced?
  • Have we selected a code of conduct we are actually willing and able to enforce?

I can’t stress the importance of the last two enough. No community should adopt a code of a conduct they think people want to see if it’s not a true representation of their community’s values and one they are willing and have the capacity to enforce. It’s immensely damaging for a community to have explicit policies that it doesn’t, for whatever reason, live out in practice. Integrity is essential for healthy community.

There’s also a danger is trying to make the perfect plan before acting. This is impossible. Sketch out a reasonable starting policy, practice it for a while and work with your community to adapt as needed over time.

If you’re trying to adopt a code of conduct and members of your community seem overly focused on legalistic analysis or want to negotiate every conceivable yet hypothetical situation before moving forward, it’s a sign that trust in governance and leadership is low.

The role of non-technical leadership

Community leaders, both those with formal authority and those without it, are critical to a community’s ability to successfully navigate change. Those with power in a community need to be on board with the change required be willing to do the work otherwise meaningful change is very unlikely to happen.

It’s entirely possible some of the FOSS communities that we have so much invested in aren’t willing or able to go through the change we need of them in this moment. For our  well-being and to avoid burn out, it’s important we develop the wisdom to be able to identify when that’s the case so we use our energy to build alternative communities.

(I do think there are strategies for bringing leaders on-board when change is needed and they are reticent to productively engage. But discussion of them is out of scope for this post.)

Some strategies for making things better

Close the leadership gap in our FLOSS communities

By now it should be clear that we have a non-technical leadership gap in our FLOSS communities and it’s harming our ability to navigate change and thrive.

To close this gap we need to develop, recognize, support, and elevate non-technical leaders. Non-technical leaders need to be recognized as valuable experts in the same way we recognize technical leaders for their expertise.

Embrace multiple viewpoints and integrate conflict productively

We need to avoid denigrating and silencing those who are reticent of change or raise concerns over adopting a code of conduct. I’m not talking about folks who show up for the sole purpose of trolling, derailing, and abusing. Let’s not increase the damage those people inflict by casting everyone who’s not automatically on board as one of them.

Conflicting points of view are crucial tool for learning. Ronald A. Heifetz in Leadership Without Easy Answers says:

“the mix of values in a society provides multiple vantage points from which to view reality. Conflict and heterogeneity are resources for social learning. Although people may not come to share one another’s values, they may learn vital information that would ordinarily be lost to view without engaging the perspectives of those who challenge them”

Respond compassionately to people’s sense of loss brought about by change

Some may respond with concern or be against a code of conduct because of the loss of power and privilege it represents to them (whether they are conscious of this or not). While we may feel that these folks have long enjoyed what they did not rightfully earn and that a redistribution of power as might occur with a code of conduct is fair, just, and necessary, we still need to respond to their sense of loss with compassion, not derision. Some will never adjust to the changing world in which they live, but many are capable of doing so and will, but they need help doing so.

Good governance and leadership prevent abuses of power

There are a handful of folks (example) who keep playing the dog whistle of impending fascism in response to their community’s proposal of adopting a code of conduct. This assertion simply has no merit and serves mostly to distract and derail. It also serves as a rallying call to those who feel disenfranchised by the changing social, political and economic environment.

Fascism and other abuses of power can happen with or without a code of conduct. Good governance, of which an explicit, written code of conduct is a part, is the antidote to abuses of power. In fact, I believe that keeping the ways your community works implicit and unwritten is more fertile ground for abuses of power than having written, communally available policies you actually follow.

Well-written codes of conduct are enforceable yet flexible enough to adapt to a community’s changing needs and circumstances over time. They are one mechanism by which conflicts can be resolved judiciously (as in, with good judgement, not related to a court of law) and consistently. Without a code of conduct or similar operating procedure, conflicts still arise but a community has no way to consistently approach or resolve them.

Some words of caution: A code of conduct won’t enable abuse of power where previously none was possible, but it might shift the the targets of that abuse or create unintended ones. It may also provide a false sense of security if there are not robust mechanisms in place to receive and respond fairly to reports. This is why a code of conduct needs to be backed up by skilled, ethical leadership and good governance infrastructure.

One last thought about compassion, unconditional positive regard, and emotional labor

Several times in this post I’ve stated we should show everyone compassion and unconditional positive regard.

When I say that, I’m not asking every individual and every given time to show compassion and unconditional positive regard for everyone else, including those who are or have engaged in abusive behavior or are members of social groups that have relatively greater power and privilege. Instead, what I ask is that people cultivate compassion and practice unconditional positive regard as they are able and willing.

Community is a shared burden, as a well as a shared resource. At any given time, some of us will be more capable of and willing to do certain things than others. Sometimes we need to concentrate on our own needs and healing.

Cultivating compassion, understanding, and unconditional positive regard is a communal activity, a communal responsibility. It’s how we’re going to move forward together towards a brighter future.

Announcing Authentic Engine, my Empathy-Based Leadership Development Consultancy

Since I last posted on the subject, I’ve made quite a bit of progress towards starting the next phase of my career. I’m excited to share that with you all now.

One of the things I’ve learned through my 4 years at Mozilla and 8+ organizing in the tech community is that most everyone wants to contribute towards making stronger, healthier, more inclusive and resilient communities. The problem is that they don’t know how and the opportunities to learn and practice the requisite skills are few and far between.

So that’s what I’m going to concentrate on: Providing the leadership learning we need and hunger for.

logo-horizontal-250pxAs such, I’ve founded a consultancy, Authentic Engine, which will focus on providing empathy-based leadership learning and practice opportunities.

There’s a huge emphasis now in our community on improving Diversity & Inclusion, as well as safety and incident response (including Code of Conduct adoption and enforcement). These are important skills our community organizers need help developing and honing. Talented folks are leading efforts here and I look forward to working with them.

I have chosen something slightly different, although complementary. I want to help develop leaders, stewards, and organizers who cultivate wisdom over time and who will be equipped to adapt to the changing needs, stresses, and resources of their communities. I want to teach people how to lead and steward authentically, utilizing their unique combination of experiences, talents, and interests.

With Authentic Engine, I’ll help people develop into the leaders and stewards our communities need now and into the future.

Here’s what I hope to accomplish this year:

  1. Launch 4 (roughly one per quarter) 3-4 hour workshops, each on a specific leadership/stewardship topic. The first will be a guided exploration of what leadership is, what kind of leader you want to be and how to become that leader. The workshops will likely debut in Portland and I’ll bring them to other cities as there is demand. The workshops will not be free, but they will be affordable and have scholarship slots.
  2. Facilitate an on-going community cohort so that folks engaged in improving themselves as leaders and stewards have a support and peer-learning network.
  3. Provide at least 100 hours of one-on-one coaching and mentoring. Anyone who takes one of my workshops will get some amount of free coaching.
  4. Help 2-3 organizations improve or develop their leadership capacity. This could take many forms from counseling an ad-hoc group of conference organizers about how best to take the next step toward formal incorporation, to helping an open source project create a training program for its contributors, to customizing one of my workshops for in-house presentation. (More ideas further down.)

I’m excited about this work because it will bring greatly needed leadership resources to our communities, helping us all to improve sustainability and resiliency. I’m also thrilled because it will allow me to draw upon and apply the varied skills and experiences I’ve developed over my entire career. This includes:

  • managing technical teams and products
  • running a small business
  • serving on the working board of a trade association (501(c)(6)
  • founding and serving on the working board of a tax-exempt non-profit (501(c)(3)
  • developing software
  • writing, publishing, and podcasting
  • organizing communities around open source projects
  • coaching and teaching others
  • documenting and improving systems & processes
  • designing, organizing, and running participatory learning events
  • managing and responding to crises, including: embezzlement, intimate partner violence, food-borne illness, unexpected budget shortfalls, and more.

This is a huge venture to undertake and I’m excited about it. I hope you’ll be part of making my journey successful.

Here are some ways you can help:

  1. Sign-up for the Authentic Engine mailing list so you’ll be notified when I launch new workshops. Register to attend a workshop (once they are launched).
  2. Let me know which leadership/stewardship topics you’re most interested by completing this interest form.
  3. If we’ve worked together and you found the experience worthwhile, write and send me a testimonial I can post to my website (and/or recommend me via LinkedIn).
  4. Recommend me to folks who could benefit from my leadership development consulting services (see above for the list of things I have experience doing).

Most of all, continue to send me your encouraging words. These mean so much to me and really help carry me through the days that feel completely overwhelming.

Wisdom is lived out in community

This Odd and Wondrous Calling (cover)
I’m in the middle of reading This Odd and Wondrous Calling: The Public and Private Lives of Two Ministers, by Lillian Daniel and Martin B. Copenhaver.

In a chapter called Expertise and Wisdom, Copenhaver provides a definition of wisdom that resonates with me deeply. He says:

Before going further with this, I need to pause to say a word about what I mean by wisdom. It has been called the woolly mammoth of ideas — big, shaggy, and elusive. Philosophers, theologians, and social scientists have all found wisdom notoriously difficult to define. In part, this is because wisdom is more than a single attribute. It is more like a cluster of attributes, including a clear-eyed view of human behavior, coupled with a keen self-understanding; a certain tolerance for ambiguity and what might be called the messiness of life; emotional resiliency; an ability to think clearly in circumstance of conflict or stress; a tendency to approach a crisis as an intriguing puzzle to be solved; an inclination to forgive and move on; humility enough to know that it is not all about you; a gift for seeing how smaller facts fit in within a larger picture; a mix of empathy and detachment; a knack for learning from lifetime experiences; a way of suspending judgement long enough to achieve greater clarity; an ability to act coupled with a willingness to embrace judicious inaction.

A bit later, he continues, explaining the importance of community in cultivating wisdom:

Unlike expertise, wisdom is lived out in community. One can become an expert by solitary study. One could, for instance, become an expert in the mating habits of turtles by reading every published study on the subject and doing one’s own field study. Wisdom, by contrast, is not a solitary activity. Wisdom is formed in the ongoing life of a community and it is exercised in community. One cannot speak of wisdom without reference to human community.

I’m sharing this here because these words speak so eloquently about the nature of the community work I strive to do, and the role I strive to fulfill.

Imagine a Tech Community…

Imagine a tech community…

That is inclusive to the point of radicalness, where people gather in solidarity at the edges.

Where everyone is able to contribute fully and authentically, whatever that means for them.

Where everyone has a part in making the community more prosperous and resilient. Where we plan collaboratively, thoughtfully balancing short- and long-term goals.

Where compassion and empathy are as present and valued as technical skill.

Where a code of conduct is an expression of shared values and but one of many tools we have and are able to use effectively to increase belonging among us.

Where expulsion is rare. Where those who transgress and those who are transgressed upon are supported alike. Where we work collectively to resolve conflict and division between us.

Where we are able to stand with the poor, the marginalized, the disenfranchised and strive to understand the world from their point of view. Where we create tech products together, that serve all of us better.

Where we are able to shift technology as a mechanism for concentrating power to one that distributes it and empowers all the world’s people.

Where we recognize that technological decisions cannot be divorced from their emotional, sociological and political contexts and we strive to take these factors into account.

Where we develop the wisdom to recognize when issues are primarily social/political not technological and we work to address them in their appropriate spheres.

Where we have the courage to speak up when we see destructive behavior because we know others will have our backs and we will not stand alone and become targets ourselves.

Where we love the difficult people as well as the easy ones and we give each the time and support they need.

Where we can gather and find fellowship in good times and bad times alike.

Where we recognize, honor and respect the great diversity in our backgrounds, life histories and worldviews. Where we strive to minimize the discord that might come from our differences and maximize the harmony of our share experiences.

…That’s the tech community I want to be a part of.

Life After Mozilla, or My Next Adventure

2015-09-24_08-11-19
Portland in Fall. It’s my favorite season here.

It’s been 2 months since my last day at Mozilla. Hard to believe that much time has past and yet it feels like it’s gone by so quickly. Rainy, gloomy weather has arrived here in Portland, for which I’m very grateful after such a long, hot summer. My plan for my first weeks away from Mozilla, most of September, was to spend as little time on the computer as possible and to intentionally not think about my next career steps. I give myself a B at following this plan. At first I did great. I did a lot of work around our house, mostly in the form of tidying and organizing. I made a bookshelf from scratch and am very happy with how it turned out. I played a lot of Civilization. I read. I slept in. I played with the dogs and took photos.

Bertie
Bertie is always around to remind me of the value of play.

And then I started reading & responding to my email.

More that a few of you were interested in how I was doing, what I was planning to do next and maybe I might be interested in this or that. It’s been amazing to hear from you, to know you value my skills and experience and want to be a part of helping me find what’s next. Not only amazing, but unexpected. Often I struggle with recognizing my own value and how I contribute to others and so explicit feedback is really helpful. Thank you everyone who’s reached out. (And know I’m still working on replying to you all.)

As good as it was to hear from everyone, it also meant that I started thinking about “what next” much sooner and in greater detail than I was ready for. I started having some conversations about projects that were exciting, but also left me agitated and unsettled.

Earlier this month I had a follow-up with my doctor that left me feeling down and depleted. It wasn’t a bad visit and was actually rather uneventful except that I left with an even longer list of asthma-related tasks to do. Pull up the carpet in our daylight basement (where my office is), have the air ducts cleaned, make the bedroom as sparse as possible, do this breathing training program, etc. And my blood pressure is a tad on the high side (in the right arm, but not the left?).

As my lack of accomplishment and I left the doctor’s I decided to stop by Powell’s as a way to cheer myself up. (I almost always want to browse books and it nearly always cheers me up.) I did a quick scan of the ‘careers’ section — which is a bit of gamble because there is so much there that’s either irrelevant (“You’ve just graduated, now what?”) or cheesy (literally, “Who Moved my Cheese?”) or just not applicable (there’s no “The Tech Industry Burned Me Out but Then I Found This Awesome, Life-Fullfilling Vocation and Here’s How You Can Too!”).

I did notice a copy of The Joy of Not Working. Huh, I thought, that sounds nice and bought it after scanning through the first couple of pages. I continued reading at home and finished that day.

What I got from the book was less factual information and more inspiration and permission to pursue the kind of work that would allow me the time to do lots of other things that I’m interested in and care about. The book’s primary audience are retirees and others who suddenly have time on their hands due to lack of employment (voluntary or otherwise). Zelinsky emphasizes the importance of cultivating many interests and community connections, not just ones associated with work. He explores just how much there is to experience in life and how much of that experience we sacrifice when we prioritize the 40+ hour workweek and how unnecessary it is to do so. Reading The Joy of Not Working made me realize a couple of things:

  • I definitely don’t want to work for someone else. Working for myself will give me the greatest freedom and agility.
  • I need to focus on fewer work-related things so that I can do them really well.
  • I need to give myself the time and the space (even if it’s scary) so that I can identity the work I truly want to be doing and how to make that possible.
  • I want to get to the point where my average work day is 4 hours so that I have plenty of do other activities that nourish my mind, body and soul.

Sounds nice, how to put this into practice? First, I identified the work projects that I would stay committed to: Stumptown Syndicate, Recompiler podcast, and whatever “working for myself” turns out to be. I’m either in the process of wrapping up or have already wrapped up my commitments to other projects. I’m not going to continue as a volunteer in any capacity for Mozilla (many feels about that, all for another blog post). Second, I’ve been making the space and doing the work to figure out what shape “working for myself” will take. I’ve thought a lot about what I’m good at and what I love doing and here’s what I’ve figured out:

  • I want to utilize and expand my experience facilitating teams, communities and organizations.
  • I want to apply and hone my aptitude for systems thinking, for motivating people to do awesome things, and for improving processes.
  • I want to apply my knowledge and love of business (nonprofit and for-profit) as well as tech.
  • I want to help businesses and organizations do better work with happier, healthier and more productive teams.

At some point I realized, “this is what consultants do!” And so I’ve been reading every book about consulting I can get my hands on. And things are clicking. I find myself saying, “I can do this. I should do this. I will do this.”

I have a name picked out. I have a marketing plan and continue to improve it as I learn more and more about marketing. I have a launch plan. I’m figuring out how to make the finances work while I drum up business. It might involve some crowdfunding. I’ll be reaching out to a lot of you for support, in whatever capacity you can provide it (hugs, referrals, a loan/gift/investment of equipment or cash, etc.). If you know someone doing this kind of work and think they would be willing to chat with me about their experience, please introduce us.

If we’ve worked together, or you know of my work so far, I hope you’re excited. I am certainly am. I’m excited about bringing the same kind of energy, vision and integrity to this new practice as I have to other projects. I’m excited at the opportunity to partner with all kinds of organizations do their work better, more prosperously.

If you want to know for sure when I launch, subscribe to my TinyLetter.

Meanwhile, I’ll be sure to keep making time for rest and for taking awesome photos of Bertie, Dora and the rest of the critter cadre.

Bertie

Fun with git submodules

Git submodules are amazingly useful. Because they provide a way for you to connect external, separate git repositories they can be used to organize your vim scripts, your dotfiles, or even a whole mediawiki deployment.

As incredibly useful as git submodules are, they can also be a bit confusing to use. This goal of this article is to walk you through the most common git submodule tasks: adding, removing and updating. We’ll also review briefly how to make changes to code you have checked out as a submodule.

I’ve created some practice repositories. Fork submodule-practice if you’d like to follow along. We’ll used these test repositories as submodules:

I’ve used version 2.3.0 of the git client for these examples. If you’re seeing something different, check your version with git --version.

Initializing a repository with submodules

First, let’s clone our practice repository:

[skade ;) ~/Work] 
christie$ git clone git@github.com:christi3k/submodule-practice.git
Cloning into 'submodule-practice'...
remote: Counting objects: 63, done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 63 (delta 9), reused 0 (delta 0), pack-reused 47
Receiving objects: 100% (63/63), 6.99 KiB | 0 bytes/s, done.
Resolving deltas: 100% (25/25), done.
Checking connectivity... done.

And then cd into the working directory:

christie$ cd submodule-practice/

Currently, this project has two submodules: furry-octo-nemesis and psychic-avenger.

When we run ls we see directories for these submodules:

[skade ;) ~/Work/submodule-practice (master)] 
christie$ ll
▕ drwxrwxr-x▏christie:christie│4  min │   4K│furry-octo-nemesis
▕ drwxrwxr-x▏christie:christie│4  min │   4K│psychic-avenger
▕ -rw-rw-r--▏christie:christie│4  min │  29B│README.md
▕ -rw-rw-r--▏christie:christie│4  min │ 110B│README.mediawiki

But if we run ls for either submodule directory we see they are empty. This is because the submodules have not yet been initialized or updated.

[skade ;) ~/Work/submodule-practice (master)] 
christie$ git submodule init
Submodule 'furry-octo-nemesis' (git@github.com:christi3k/furry-octo-nemesis.git) registered for path 'furry-octo-nemesis'
Submodule 'psychic-avenger' (git@github.com:christi3k/psychic-avenger.git) registered for path 'psychic-avenger'

git submodule init copies the submodule names, urls and other details from .gitmodules to .git/config, which is where git looks for config details it should apply to your working copy.

git submodule init does not update or otherwise alter information in .git/config. If you have changed .gitmodules for any submodule already initialized, you’ll need to deinit and init the submodule again for changes to be reflected in .git/config.

You can initialize specific submodules by specifying their name:

git submodule init psychich-avenger

At this point you could customized git submodule urls for use in your local checkout by editing them in .git/config before proceeding to git submodule update.

Now let’s actually checkout the submodules with submodule update:

skade ;) ~/Work/submodule-practice (master)] 
christie$ git submodule update --recursive
Cloning into 'furry-octo-nemesis'...
remote: Counting objects: 6, done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 6
Receiving objects: 100% (6/6), done.
Checking connectivity... done.
Submodule path 'furry-octo-nemesis': checked out '1c4b231fa0bcfd5ce8b8a2773c6616689032d353'
Cloning into 'psychic-avenger'...
remote: Counting objects: 25, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 25 (delta 1), reused 0 (delta 0), pack-reused 15
Receiving objects: 100% (25/25), done.
Resolving deltas: 100% (3/3), done.
Checking connectivity... done.
Submodule path 'psychic-avenger': checked out '169c5c56154f58fd745352c4f30aa0d4a1d7a88e'

Note: The --recursive flag tells git to recurse into submodule directories and run update on any submodules those submodules include. It’s not needed for this example, but I’ve included it here anyway since it’s common for projects to have nested submodules.

Now when we run ls on either directory, we see they now contain our submodule’s files:

[skade ;) ~/Work/submodule-practice (master)] 
christie$ ls furry-octo-nemesis/
▕ -rw-rw-r--▏42 sec │  52B│README.md

[skade ;) ~/Work/submodule-practice (master)] 
christie$ ls psychic-avenger/
▕ -rw-rw-r--▏46 sec │ 133B│README.md
▕ -rw-rw-r--▏46 sec │   0B│other.txt

Note: It’s possible to run init and update in one command with git submodule update --init --recursive

Adding a git submodule

We’ll start in the working directory of submodule-practice.

To add a submodule, use:

git submodule add <git-url>

Let’s try adding sample project scaling-octo-wallhack as a submodule.

[2495][skade ;) ~/Work/submodule-practice (master)] 
christie$ git submodule add git@github.com:christi3k/scaling-octo-wallhack.git
Cloning into 'scaling-octo-wallhack'...
remote: Counting objects: 19, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 19 (delta 1), reused 0 (delta 0), pack-reused 9
Receiving objects: 100% (19/19), done.
Resolving deltas: 100% (3/3), done.
Checking connectivity... done.

Note: If you want the submodule to be cloned into a directory other than ‘scaling-octo-wallhack’ then you need to specify a directory to clone into as you would when cloning any other project. For example, this command will clone psychic-avenger to the subdirectory submodules:

christie$ git submodule add git@github.com:christi3k/scaling-octo-wallhack.git submodules/scaling-octo-wallhack

Let’s see what git status tells us:

[skade ;) ~/Work/submodule-practice (master +)] 
christie$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   .gitmodules
	new file:   scaling-octo-wallhack

And running ls we see that there are files in scaling-octo-wallhack directory:

[skade ;) ~/Work/submodule-practice (master +)] 
christie$ ll scaling-octo-wallhack/
▕ -rw-rw-r--▏christie:christie│<  min │ 180B│README.md
▕ -rw-rw-r--▏christie:christie│<  min │   0B│cutting-edge-changes.txt
▕ -rw-rw-r--▏christie:christie│<  min │   0B│file1.txt
▕ -rw-rw-r--▏christie:christie│<  min │   0B│file2.txt

Specifying a branch

When you add a git submodule, git makes some assumptions for you. It sets up a remote repository to the submodule called ‘origin’ and it checksout the ‘master’ branch for you. In many cases you may no want to use the master branch. Luckily, this is easy to change.

There are two methods to specific which branch of the submodule should be checked out by your project.

Method 1: Specify a branch in .gitmodules

Here’s what the modified section of .gitmodules looks like for scaling-octo-wallhack:

[submodule "scaling-octo-wallhack"]
  path = scaling-octo-wallhack
  url = git@github.com:christi3k/scaling-octo-wallhack.git
  branch  = REL_1

Be sure to save .gitmodules and then run git submodule update --remote:

[skade ;( ~/Work/submodule-practice (master *+)] 
christie$ git submodule update --remote
Submodule path 'psychic-avenger': checked out 'fba086dbb321109e5cd2d9d1bc3b59478dacf6ee'
Submodule path 'scaling-octo-wallhack': checked out '88d66d5ecc58d2ab82fec4fea06ffbfd2c55fd7d'

Method 2: Checkout specific branch in submodule directory

In the submodule directory, checkout the branch you want with git checkout origin/branch-name:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((b49591a...))] 
christie$ git checkout origin/REL_1
Previous HEAD position was b49591a... Cutting-edge changes.
HEAD is now at 88d66d5... Prep Release 1.

Either method will result will yield the following from git status:

[skade ;) ~/Work/submodule-practice (master *+)] 
christie$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   .gitmodules
	new file:   scaling-octo-wallhack

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   scaling-octo-wallhack (new commits)

Now let’s stage and commit the changes:

[skade ;) ~/Work/submodule-practice (master *+)] 
christie$ git add scaling-octo-wallhack

[skade ;) ~/Work/submodule-practice (master +)] 
christie$ git commit -m "Add scaling-octo-wallhack submodule, REL_1."
[master 4a97a6f] Add scaling-octo-wallhack submodule, REL_1.
 2 files changed, 4 insertions(+)
 create mode 160000 scaling-octo-wallhack

And don’t forget to push them to our remote repository so they are available for others:

[skade ;) ~/Work/submodule-practice (master)] 
christie$ git push -n origin master 
To git@github.com:christi3k/submodule-practice.git
   7e6d09e..4a97a6f  master -> master

(Note the -n flag means ‘dry run’, that is ‘do everything except actually send the updates.’ I recommend using this when available with commands that have potentially destructive results, including push and merge.)

Looks good, do it for real now:

[skade ;) ~/Work/submodule-practice (master)] 
christie$ git push origin master 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 439 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To git@github.com:christi3k/submodule-practice.git
   7e6d09e..4a97a6f  master -> master

Removing a git submodule

Removing a submodule is a bit trickier than adding one.

Deinitialize

First, deinit the submodule with git submodule deinit :

[skade ;) ~/Work/submodule-practice (master)]
christie$ git submodule deinit psychic-avenger
Cleared directory 'psychic-avenger'
Submodule 'psychic-avenger' (git@github.com:christi3k/psychic-avenger.git) unregistered for path 'psychic-avenger'

This command removes the submodule’s confg entries in .git/config and .gitmodules and it removes files from the submodule’s working directory. This command will delete untracked files, even when they are listed in .gitignore.

Note: You can also use this command if you simply want to prevent having a local checkout of the submodule in your working tree, without actually removing the submodule from your main project.

Let’s check our work:

[skade ;) ~/Work/submodule-practice (master)]
christie$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

This shows no changes because git submodule deinit only makes changes to our local working copy.

Running ls we also see the directories are still present:

[skade ;) ~/Work/submodule-practice (master)]
christie$ ll
▕ drwxrwxr-x▏christie:christie│4 day │ 4K│furry-octo-nemesis
▕ drwxrwxr-x▏christie:christie│16 sec │ 4K│psychic-avenger
▕ -rw-rw-r--▏christie:christie│4 day │ 29B│README.md
▕ -rw-rw-r--▏christie:christie│4 day │ 110B│README.mediawiki

[skade ;) ~/Work/submodule-practice (master)]

Remove with git rm

To actually remove the submodule from your project’s repository, use git rm:

[skade ;) ~/Work/submodule-practice (master)]
christie$ git rm psychic-avenger
rm 'psychic-avenger'

Let’s check our work:

[skade ;) ~/Work/submodule-practice (master +)]
christie$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)

modified: .gitmodules
deleted: psychic-avenger

These changes have been staged by git automatically, so to see what has changed about .gitmodules, use --cached flag or its alias --staged:

[skade ;) ~/Work/submodule-practice (master +)]
christie$ git diff --cached
diff --git a/.gitmodules b/.gitmodules
index dec1204..e531507 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
[submodule "furry-octo-nemesis"]
path = furry-octo-nemesis
url = git@github.com:christi3k/furry-octo-nemesis.git
-[submodule "psychic-avenger"]
- path = psychic-avenger
- url = git@github.com:christi3k/psychic-avenger.git
diff --git a/psychic-avenger b/psychic-avenger
deleted file mode 160000
index fdd4b36..0000000
--- a/psychic-avenger
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit fdd4b366458757940d7692b61e22f4d1b21c825a

So we see that in .gitmodules, lines related to psychic-avenger have been removed and that the psychic-avenger directory and commit hash has also been removed.

And a directory listing shows the files are no longer in our working directory:

christie$ ll
▕ drwxrwxr-x▏christie:christie│4 day │ 4K│furry-octo-nemesis
▕ -rw-rw-r--▏christie:christie│4 day │ 29B│README.md
▕ -rw-rw-r--▏christie:christie│4 day │ 110B│README.mediawiki

Removing all reference to the submodule (optional)

For whatever reason, git does not remove all trace of the submodule even after these commands. To completely remove all reference, you need to also delete the .git/modules entry to really have it be gone:

[skade ;) ~/Work/submodule-practice (master)]
christie$ rm -rf .git/modules/psychic-avenger

Note: This probably optional for most use-cases. The only time you might run into trouble if you leave this reference is if you later add a submodule of the same name. In that case, git will complain and ask you to pick a different name or to simply checkout the submodule from the remote source it already knows about.

Also, be careful with rm -rf because it doesn’t prompt you for a confirmation and there’s no dry-run flag.

Commit changes

Now we commit our changes:

[skade ;) ~/Work/submodule-practice (master +)]
christie$ git commit -m "Remove psychic-avenger submodule."
[master 7833c1c] Remove psychic-avenger submodule.
2 files changed, 4 deletions(-)
delete mode 160000 psychic-avenger

Looks good, let’s push our changes:

[skade ;) ~/Work/submodule-practice (master)]
christie$ git push -n origin master
To git@github.com:christi3k/submodule-practice.git
d89b5cb..7833c1c master -&gt; master

Looks good, let’s do it for real:

[skade ;) ~/Work/submodule-practice (master)]
christie$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 402 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@github.com:christi3k/submodule-practice.git
d89b5cb..7833c1c master -&gt; master

Updating submodules within your project

The simplest use case for updating submodules within your project is when you simply want to pull in the most recent version of that submodule or want to change to a different branch.

There are two methods for updating modules.

Method 1: Specify a branch in .gitmodules and use git submodule update --remote

Using this method, you first need to ensure that the branch you want to use is specified for each submodule in .gitmodules.

Let’s take a look at the .gitmodules file for our sample project:

[submodule "furry-octo-nemesis"]
  path = furry-octo-nemesis
  url = git@github.com:christi3k/furry-octo-nemesis.git
[submodule "psychic-avenger"]
  path = psychic-avenger
  url = git@github.com:christi3k/psychic-avenger.git
  branch = RELEASE_E
[submodule "scaling-octo-wallhack"]
  path = scaling-octo-wallhack
  url = git@github.com:christi3k/scaling-octo-wallhack.git

The submodule psychic-avenger is set to checkout branch RELEASE_E and both furry-octo-nemesis and scaling-octo-wallhack will checkout master because no branch is specified.

Edit .gitsubmodules

To change the branch that is checked out, update the value of branch:

[submodule "scaling-octo-wallhack"]
  path = scaling-octo-wallhack
  url = git@github.com:christi3k/scaling-octo-wallhack.git
  brach = REL_2

Now scaling-octo-wallhack is set to checkout the REL_2 branch.

Update with git submodule update –remote

[skade ;) ~/Work/submodule-practice (master *)] 
christie$ git submodule update --remote
Submodule path 'scaling-octo-wallhack': checked out 'e845f5431119b527b7cde1ad138a373c5b2d4ec1'

And if we cd into scaling-octo-wallhack and run branch -vva we confirm we’ve checked out the REL_2 branch:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((e845f54...))] 
christie$ git branch -vva
* (detached from e845f54) e845f54 Release 2.
  master                  b49591a [origin/master] Cutting-edge changes.
  remotes/origin/HEAD     -> origin/master
  remotes/origin/REL_1    88d66d5 Prep Release 1.
  remotes/origin/REL_2    e845f54 Release 2.
  remotes/origin/master   b49591a Cutting-edge changes.

Method 2: git fetch and git checkout within submodule

First, change into the directory of the submodule you wish to update.

fetch from remote repository

Then run git fetch origin to grab any new commits:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((b49591a...))] 
christie$ git fetch origin 
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:christi3k/scaling-octo-wallhack
   e845f54..1cc1044  REL_2      -> origin/REL_2

Here was can see that the last commit for the REL_2 branch changed from e845f54 to 1cc1044.

Running branch -vva confirms this and that we haven’t changed which commit is checked out yet:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((88d66d5...))] 
christie$ git branch -vva
* (detached from 88d66d5) 88d66d5 Prep Release 1.
  master                  b49591a [origin/master] Cutting-edge changes.
  remotes/origin/HEAD     -> origin/master
  remotes/origin/REL_1    88d66d5 Prep Release 1.
  remotes/origin/REL_2    1cc1044 Hotfix for Release 2 branch.
  remotes/origin/master   b49591a Cutting-edge changes.

Checkout branch

So now we can re-checkout the REL_2 remote branch:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((88d66d5...))] 
christie$ git checkout origin/REL_2
Previous HEAD position was 88d66d5... Prep Release 1.
HEAD is now at 1cc1044... Hotfix for Release 2 branch.

Let’s check our work with branch -vva:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((1cc1044...))] 
christie$ git branch -vva
* (detached from origin/REL_2) 1cc1044 Hotfix for Release 2 branch.
  master                       b49591a [origin/master] Cutting-edge changes.
  remotes/origin/HEAD          -> origin/master
  remotes/origin/REL_1         88d66d5 Prep Release 1.
  remotes/origin/REL_2         1cc1044 Hotfix for Release 2 branch.
  remotes/origin/master        b49591a Cutting-edge changes.

Commiting the changes

Moving back to our main project directory, let’s check our work with git status && git diff:

[skade ;) ~/Work/submodule-practice (master *)] 
christie$ git status && git diff
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   scaling-octo-wallhack (new commits)

no changes added to commit (use "git add" and/or "git commit -a")
diff --git a/scaling-octo-wallhack b/scaling-octo-wallhack
index 88d66d5..1cc1044 160000
--- a/scaling-octo-wallhack
+++ b/scaling-octo-wallhack
@@ -1 +1 @@
-Subproject commit 88d66d5ecc58d2ab82fec4fea06ffbfd2c55fd7d
+Subproject commit 1cc104418a6a24b9a3cc227df4ebaf707ea23b49

Notice that there are no changes to .gitmodules with this method. Instead, we’ve simply changed the commit hash that the super project is pointing to for this submodule.

Now let’s add, commit and push our changes:

[skade ;) ~/Work/submodule-practice (master *)] 
christie$ git add scaling-octo-wallhack

[skade ;) ~/Work/submodule-practice (master +)] 
christie$ git commit -m "Updating to current REL_2."
[master 5ddbe87] Updating to current REL_2.
 1 file changed, 1 insertion(+), 1 deletion(-)

[skade ;) ~/Work/submodule-practice (master)] 
christie$ git push -n origin master
To git@github.com:christi3k/submodule-practice.git
   4a97a6f..5ddbe87  master -> master

[skade ;) ~/Work/submodule-practice (master)] 
christie$ git push origin master
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 261 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To git@github.com:christi3k/submodule-practice.git
   4a97a6f..5ddbe87  master -> master

what’s the difference between git submodule update and git submodule update –remote?

Note: git submodule update –remote looks at the value you have in .gitmodules for branch. If there isn’t a value there, it assumes master. git submodule update looks at your repository has for the commit of the submodule project and checks that commit out. Both checkout to a detached state by default unless you specify –merge or –rebase.

These two commands have the ability to step on each other. If you have checked out a specific commit in the submodule directory, it’s possible for it to be different than the commit that would be checked out by git submdoule update –remote specificied in the branch value of .gitmodules.
Likewise, simply looking at the branch value in .gitmodules does not guarentee that’s the branch you have checked out for the submodule. When in doubt, cd to the submodule directory and run git branch -vva. git branch -vva is your friend!

When a subbmodule has been removed

When a submodule has been removed from a repository, what’s the best way to update your working directory to reflect this change?

The answer is that it depends on whether or not you have local, untracked files in the submodule directory that you want to keep.

Method 1: deinit and then fetch and merge

Use this method if you want to completely remove the submodule directory even if you have local, untracked files in it.

Note: In the following examples, we’re working in another checkout of our submodule-practice.

First, use git submodule deinit to deinitialize the submodule:

[skade ;) ~/Work/submodule-elsewhere (master *)] 
christie$ git submodule deinit psychic-avenger
error: the following file has local modifications:
    psychic-avenger
(use --cached to keep the file, or -f to force removal)
Submodule work tree 'psychic-avenger' contains local modifications; use '-f' to discard them

We have untracked changes, so we need to use -f to remove them:

[skade ;( ~/Work/submodule-elsewhere (master *)] 
christie$ git submodule deinit -f psychic-avenger
Cleared directory 'psychic-avenger'
Submodule 'psychic-avenger' (git@github.com:christi3k/psychic-avenger.git) unregistered for path 'psychic-avenger'

Now fetch changes from the remote repository and merge them:

[skade ;) ~/Work/submodule-elsewhere (master)] 
christie$ git fetch origin 
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 2), reused 3 (delta 2), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:christi3k/submodule-practice
   666af5d..6038c72  master     -> origin/master

[skade ;) ~/Work/submodule-elsewhere (master)] 
christie$ git merge origin/master 
Updating 666af5d..6038c72
Fast-forward
 .gitmodules     | 3 ---
 psychic-avenger | 1 -
 2 files changed, 4 deletions(-)
 delete mode 160000 psychic-avenger

Running ls on our project directory shows that the all of psychic-avenger’s files have been removed:

[skade ;) ~/Work/submodule-elsewhere (master)] 
christie$ ll 
▕ drwxrwxr-x▏christie:christie│3  hour│   4K│furry-octo-nemesis
▕ drwxrwxr-x▏christie:christie│5  min │   4K│scaling-octo-wallhack
▕ -rw-rw-r--▏christie:christie│3  hour│  29B│README.md
▕ -rw-rw-r--▏christie:christie│3  hour│ 110B│README.mediawiki

Method 2: fetch and merge and clean up as needed

Use this method if you have local, untracked (and/or ignored) changes that you want to keep, or if you want to remove files manually.

First, fetch changes from the remote repository and merge them with your local branch:

[skade ;) ~/Work/submodule-elsewhere (master)]
christie$ git fetch origin
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:christi3k/submodule-practice
d89b5cb..7833c1c master -> origin/master

[skade ;) ~/Work/submodule-elsewhere (master)]
christie$ git merge origin/master
Updating d89b5cb..7833c1c
warning: unable to rmdir psychic-avenger: Directory not empty
Fast-forward
.gitmodules | 3 ---
psychic-avenger | 1 -
2 files changed, 4 deletions(-)
delete mode 160000 psychic-avenger

Note the warning “unable to rm dir…” and let’s check our work:

[skade ;) ~/Work/submodule-elsewhere (master)]
christie$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add ..." to include in what will be committed)

psychic-avenger/

nothing added to commit but untracked files present (use "git add" to track)

No uncommited or staged changes, but the directory that was our submodule psychic-avenger is now untracked. Running ls shows that there are still files in the directory, too:

[skade ;( ~/Work/submodule-elsewhere (master)]
christie$ ll psychic-avenger/
▕ -rw-rw-r--▏christie:christie│30 min │ 192B│README.md

Now you can clean up files as you like. In this example we’ll delete the entire psychic-avenger directory:

[skade ;) ~/Work/submodule-elsewhere (master)]
christie$ rm -rf psychic-avenger

Working on projects checked out as submodules

Working on projects checked out as submodules is rather straight-forward, particularly if you are comfortable with git branching and make liberal use of git branch -vva.

Let’s pretend that scaling-octo-wallhack is an extension that I’m developing for my project submodule-practice. I want to work on the project while it’s checked out as a submodule because doing so makes it easy to test the extension within my larger project.

Create a working branch

First switch the the branch that you want to use as the base for your work. I’m going to use local tracking branch master, which I’ll first ensure is up to date with the remote origin/master:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((1cc1044...))] 
christie$ git branch -vva
* (detached from origin/REL_2) 1cc1044 Hotfix for Release 2 branch.
  master                       b49591a [origin/master] Cutting-edge changes.
  remotes/origin/HEAD          -> origin/master
  remotes/origin/REL_1         88d66d5 Prep Release 1.
  remotes/origin/REL_2         1cc1044 Hotfix for Release 2 branch.
  remotes/origin/master        b49591a Cutting-edge changes.

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack ((b49591a...))] 
christie$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

If master had not been up-to-date with orgin/master, I would have merged.

Next, let’s create a tracking branch for this awesome feature we’re going to work on:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (master)] 
christie$ git checkout -b awesome-feature
Switched to a new branch 'awesome-feature'

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature)] 
christie$ git branch -vva
* awesome-feature       b49591a Cutting-edge changes.
  master                b49591a [origin/master] Cutting-edge changes.
  remotes/origin/HEAD   -> origin/master
  remotes/origin/REL_1  88d66d5 Prep Release 1.
  remotes/origin/REL_2  1cc1044 Hotfix for Release 2 branch.
  remotes/origin/master b49591a Cutting-edge changes.

Do some work, add and commit changes

No we’ll do some work on the feature, add and commit that work:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature)] 
christie$ touch awesome_feature.txt

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature)] 
christie$ git add awesome_feature.txt 

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature +)] 
christie$ git commit -m "first round of work on awesome feature"
[awesome-feature 005994b] first round of work on awesome feature
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 awesome_feature.txt

Push to remote repository

Now we’ll push that to our remost repository so others can contribute:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature)] 
christie$ git push -n origin awesome-feature 
To git@github.com:christi3k/scaling-octo-wallhack.git
 * [new branch]      awesome-feature -> awesome-feature

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature)] 
christie$ git push origin awesome-feature 
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 265 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To git@github.com:christi3k/scaling-octo-wallhack.git
 * [new branch]      awesome-feature -> awesome-feature

Switch back to remote branch, headless checkout

If we’d like to switch back to a remote branch, we can:

[skade ;) ~/Work/submodule-practice/scaling-octo-wallhack (awesome-feature)] 
christie$ git checkout origin/REL_2
Note: checking out 'origin/REL_2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 1cc1044... Hotfix for Release 2 branch.

Using this new branch to collaborate

To try this awesome feature in another checkout, use git fetch:

[skade ;) ~/Work/submodule-elsewhere/scaling-octo-wallhack ((1cc1044...))] 
christie$ git fetch origin 
remote: Counting objects: 2, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 2 (delta 1), reused 2 (delta 1), pack-reused 0
Unpacking objects: 100% (2/2), done.
From github.com:christi3k/scaling-octo-wallhack
 * [new branch]      awesome-feature -> origin/awesome-feature

If you just want to try the feature, checkout orgin/branch:

[2724][skade ;) ~/Work/submodule-elsewhere/scaling-octo-wallhack ((1cc1044...))] 
christie$ git checkout origin/awesome-feature 
Previous HEAD position was 1cc1044... Hotfix for Release 2 branch.
HEAD is now at 005994b... first round of work on awesome feature

If you plan to work on the feature, create a tracking branch:

[2725][skade ;) ~/Work/submodule-elsewhere/scaling-octo-wallhack ((005994b...))] 
christie$ git checkout -b awesome-feature 
Switched to a new branch 'awesome-feature'

Acknowledgements

Thanks GPHemsley for helping me figure out git submodules within the context of our MozillaWiki work. I couldn’t have written this post without those conversations or the notes I took during them.

Additional Resources

Update 19 Feb: Fixed typos and added ‘Additional Resources’ section.