1. 65
  1.  

  2. 23

    If your main complaint is that email is horrible to work with, the issue is most likely not email, it’s probably your mail client.

    I know a lot of people on here love git-by-email and everyone has their own reasons for why, but I get frustrated when I see messages like this. I’ve been using email for over 20 years now over multiple clients. I’ve even contributed to a mail client.

    Most of my frustrations with email go away when I use group chat, instant messaging, and synchronized “what do I need to work on” dashboards (such as GitHub’s pull request view). Email is nice for writing messages to friends you haven’t talked to in a year, event invites, and newsletters.

    In my opinion it’s awful for transactional stuff, because the overhead (setting up filters, archiving stuff) gets in the way of doing what you need. I also find it awful for stuff that needs to be machine parsed, because it’s a sloppy format, does not have a good concept of a “query” (there’s an API call to GitHub to tell me all open pull requests on a repository, for a similar thing in email you’d have to build something yourself) and emails come with a lot of cruft around them like signatures and such.

    If I think email is bad for transactional tasks and machine-parseable tasks, and reviewing code is a transactional machine-parseable task, my problem is with email.

    1. 2

      In my opinion it’s awful for transactional stuff, because the overhead (setting up filters, archiving stuff) gets in the way of doing what you need

      Those things are optional and time consuming. So don’t do them.

      I set up my filters about a decade ago, and only touch them when I join a high volume mailing list – so, maybe once a year or two. I don’t archive messages. My inbox goes back slightly more than half my lifetime.

    2. 10

      Nice view on how the email flow works. Though, I don’t agree with some things.

      The only reason that merge button was used on Github was because Github can’t seem to mark the pull request as merged if it isn’t done by the button.

      No, it does. I merge locally all the time, and GitHub instantly marks a PR as merged when I push. In fact, I primarily host repos at GitLab and keep a mirror on GitHub. I accept PRs on GitHub (the mirror) as well to keep things easy for contributors. I manually merge these locally, and push the updated branch to GitLab. GitLab in turn syncs the GitHub mirror, and the PR on GitHub is marked as merged in a matter of seconds.

      …we have to mess with the commits before merging so we’re always force-pushing to the git fork of the author of the pull request (which they have to enable on the merge request, if they don’t we first have to tell them to enable that checkbox)

      Yes, of course you’ve to mess with them. But after doing that, don’t even bother to push to the contributors branch. Just merge it into the target branch yourself and push. Both GitLab and GitHub will instantly mark the PR as merged. It is the contributors job to keep his branch up to date, and he doesn’t even have to for you to be able to do your job.

      I understand that you like the email workflow, which is great. But I don’t agree with some arguments for it that are made here.

      Thanks for sharing though!

      1. 7

        No, it does. I merge locally all the time, and GitHub instantly marks a PR as merged when I push.

        In the article they talk about wanting to rebase first. If you do that locally, GitHub has no way to know that the rebased commits you pushed originally came from the PR, so it can’t close them automatically. It does work when you push outside GitHub without rebasing tho.

        1. 2

          IIRC, can’t you rebase, (force) push to the PR branch, then merge and push and it’ll close? More work in that case but not impossible. Just if you rebase locally then push to ma(ster|in) then github has no easy way to know the pr is merged without doing fuzzy matching of commit/pr contents which would be a crazy thing to implement in my opinion.

          1. 3

            Typically the branch is on someone else’s fork, not yours.

            1. 2

              In Github, you can push to anothers branch if they have made it a PR in your project. Not sure if force push works, never tried. But I still feel it’s a hassle, you need to set up a new remote in git.

              In Gitlab, apparently, you have to ask the branch owner to set some checkbox in Gitlab so that you can push to the branch.

              1. 3

                In Gitlab, apparently, you have to ask the branch owner to set some checkbox in Gitlab so that you can push to the branch.

                That is the case in GitHub as well. (Allow edit from maintainers). It is enabled by default so I’ve never had to ask someone to enable it. Maybe it is not enabled by default on GitLab?

                1. 1

                  I can confirm that it is disabled by default on GitLab.

      2. 5

        This article nicely illustrates how easy the git email flow is for developers/contributors, but how about for maintainers?

        For instance, how do I easily apply a patch sent to me, if I use the gmail/fastmail web interface? If web-mail is frowned upon, does it work if I use thunderbird/outlook/something-else? Or does it basically require me to use mutt?

        How about managing different patches from different sources at the same time? Github conveniently suggests you create a local copy of the PR’ed branch, meaning you can easily change between different PRs. How does this work with git email flow? Do I just create those branches myself, or is there an easier way to do it?

        What about very large patches? I recently applied a code formatter to a project I contribute to, resulting in a 4MB diff. Not all email clients/servers handle arbitrarily large files well.

        I’ve seen enough descriptions about how git-send-email works from a contributors perspective, but I would really appreciate it, if someone would write down how they then receive and review patches in this flow.

        1. 6

          As long as your e-mail client/interface doesn’t somehow mangle the original message, the simplest solution would probably be to simply copy the message as a whole and then run something like xsel -ob | git am in the repository. I’d reckon this is much easier than setting up some more UNIX-like e-mail client.

          1. 6

            Although his workflow is obviously not representative of most maintainers, Greg K-H’s writeup was nonetheless fascinating.

            1. 1

              That does indeed look fascinating, and like it addresses some of my questions. Will take a closer look later.

            2. 3

              What about very large patches?

              git request-pull can be used for this purpose, it generates emails with a URL from which the reviewer can pull the changes. It’s generally used for subsystem maintainers in large projects to merge their (independent) histories upstream, but it can also be used to handle large changes which would be unwieldly in patch form.

              1. 3

                For instance, how do I easily apply a patch sent to me, if I use the gmail/fastmail web interface? If web-mail is frowned upon, does it work if I use thunderbird/outlook/something-else? Or does it basically require me to use mutt?

                You can certainly use mutt or Gnus if you want. Most projects using git-by-email use mailing lists, some are fancy with download buttons to get the patches. Most of the time you can pass the output of curl fetching the mailing list page directly to patch. Quoting the manual

                patch tries to skip any leading garbage, apply the diff, and then skip any trailing garbage. Thus you could feed an article or message containing a diff listing to patch, and it should work.

                I’ve done this as recently as this week, when I found an interesting patch to u-boot.

                If a mailing list or other web view isn’t available, then you can either set one up (patchwork is the defacto standard) or find a client that doesn’t break plaintext emails. Last I checked, receiving patches via Gmail’s web interface was difficult (but sometimes possible if you hunt down the “raw message” link), I haven’t checked Fastmail. If you don’t want to use a TUI or GUI email client, you can configure getmail to only fetch emails from specific folders or labels, and that will create mbox files you can use with git am.

                How about managing different patches from different sources at the same time? Github conveniently suggests you create a local copy of the PR’ed branch, meaning you can easily change between different PRs. How does this work with git email flow? Do I just create those branches myself, or is there an easier way to do it?

                Branches are lightweight, create them for however many things you want to work on at the same time. I usually don’t use branches at all, instead using stgit, and just import patches and push and pop them as needed.

                What about very large patches? I recently applied a code formatter to a project I contribute to, resulting in a 4MB diff. Not all email clients/servers handle arbitrarily large files well.

                You can breakup that work into smaller chunks, to avoid too much disruption to other patches that might be in flight. Nothing stops you from linking to an external patch, though I would probably prefer instructions on how to run the tool myself, and just forgo the patch in that case.

                1. 2
                  1. 1

                    I wondered about the same thing. After a very long unfruitful search on the internet, @fkooman pointed me to git am - Apply a series of patches from a mailbox, which pretty much takes care of everything. It would have been helpful if git-send-email.io had a pointer to that, or maybe I missed it..

                  2. 4

                    Also after working in Gitlab for most of the things I do on postmarketOS I really like how quickly sourcehut pages load and that I just can get all info from the patch without clicking on tabs to switch between comments, diffs and commit messages with loading times in between.

                    Reading this made me realize that while I have a slight preference for email over web-based pull requests, I have a strong preference for “loads in a handful of milliseconds no matter how old the hardware is” and a strong preference for “allows you to interface with it using the client of your choice”.

                    Personally I don’t care where the patches come from, whether it’s email, pastebin, or a link to a git remote that’s shared in our IRC/Matrix channel. As long as we can discuss it and ensure it does what it needs to do that’s good enough.

                    1. 3

                      I’ve been taking a look at email-based flows but I somehow find it quite limiting when compared to something like GitLab. Let me just list a few points in no particular order:

                      • How to marry email-based flows and CI? For instance, how to show CI status and how to prevent merges if CI fails?
                      • How do I approve a merge (after reviewing it) but have it merged automatically upon CI completion?
                      • How to associate project issue numbers in email messages? My email client has no idea what #123 means.
                      • How to lock and moderate discussions on particular patches? Wouldn’t I need to be the mailing list admin for that?
                      • How to make sure that old patches (which in merge request terms are outdated because someone force-pushed the feature branch) are marked as such? I imagine I’d need to send emails to all threads that currently have old patches and somehow invalidate those. Is this an automatic thing that I’m unaware of? I imagine it might get tiresome fast.

                      Maybe I’m just super ignorant about the current state of email-based flow automation that exists which is quite possible. Though from my current naive standpoint, it would appear like email-based flow removes a lot of the existing automation and mechanisms that are in place in GitHub/GitLab and put all of that burden on the maintainer or contributors.

                      1. 2

                        In theory, few of these are particularly hard:

                        How to marry email-based flows and CI? For instance, how to show CI status and how to prevent merges if CI fails?

                        If the email workflow goes to a mailing list, it’s easy to subscribe a bot to that list and have it apply the patch and reply to the message with the CI results.

                        How do I approve a merge (after reviewing it) but have it merged automatically upon CI completion?

                        A bot subscribed to the list can read a signed (S/MIME / GPG / Whatever you prefer) email from one of the designated maintainers and handle the merge.

                        How to associate project issue numbers in email messages? My email client has no idea what #123 means.

                        There’s nothing (other than DKIM and friends) stopping your mailing list from rewriting the messages to include hyperlinks to your issue tracker.

                        How to lock and moderate discussions on particular patches? Wouldn’t I need to be the mailing list admin for that?

                        Yes, but presumably you would be list admin on mailing lists for the project for which you are maintainer. That said, preventing someone resurrecting a thread on a mailing list is basically impossible: you can auto-bounce messages with the same title and thread ID, but there’s nothing stoping someone starting a new thread. On the other hand, the same applies on GitHub: just because you close and lock an issue or PR doesn’t prevent someone from filing an identical one.

                        How to make sure that old patches (which in merge request terms are outdated because someone force-pushed the feature branch) are marked as such? I imagine I’d need to send emails to all threads that currently have old patches and somehow invalidate those. Is this an automatic thing that I’m unaware of? I imagine it might get tiresome fast.

                        I’m not quite sure what you mean here, but it’s easy to make a bot automatically post a follow-up email.

                        By the time that you’ve done all of this; however, you’re depending heavily on a mail client with a good threading display and you’ve implemented a large chunk of a GitHub / GitLab / GOGS / whatever system. The question that you’d have to ask yourself is what value you get from this that you wouldn’t get from the web-based version.

                        One potentially interesting intermediate step might be to write an IMAP proxy to something like GitHub, which would expose all of the PRs / Issues as threads.

                        1. 1

                          Thanks for the answers. I suppose I should have phrased my questions better. In general I was not so much interested in whether it was technologically feasible to achieve what I asked but rather which off-the-shelf tools one would use in order to get those. SourceHut probably comes close but it seems that one is then also tied to their platform.

                        2. 1

                          I’d like to have an answer on this as well.

                        3. 3

                          Once you have a reasonable volume of pull requests the branches of those pull requests get outdated quickly meaning they have to be rebased before merging or every change will have an extra merge commit in the history.

                          Is that extra merge commit a problem, or is it just an object the author sees as noise and wishes were not there? I’m very much a rebaser, but others on my team just merge, and any mess I perceive falls into history soon enough.

                          1. 2

                            This is a nice write up! I have never used email flow and it always felt as something old and dying. Recently, though, there has been a number of positive reviews about sr.ht and since it uses email flow of that as well.

                            My biggest problem is how to combine those two approaches together or how to migrate from one to the other. I certainly wouldn’t want to put pressure on my colleagues to learn a completely different flow of working.

                            1. 1

                              You can always use git am with URL from GitHub/GitLab. Ideally these services would allow to send PRs via emailing the patch to email in format like user/repo@github.com reducing the steps needed for the author (no need for creating account). This would give the best of both worlds.

                            2. 2

                              Too bad I didn’t answer to this on time, because I have a similar story to share. At work we moved to Mercurial + Phabricator to Git + GitHub for a project (client choice).

                              We use trunk based development, meaning very short-lived feature branches. This is close to what you are looking for (fast-forward merge only).

                              With Phabricator, patches are sent, which is very similar to the email workflow.

                              However, GitLab/GitHub interface is easier to understand for beginners, and even Phabricator which is a web interface is complicated.

                              For the transition between Mercurial and Git (only the trunk got migrated first), I had to import patches with git am and I can say that it is not so easy, even with -3 it may refuses to do a 3-way merge, that should be able to apply. In comparison, git rebase --onto works perfectly for rebasing a short-lived branch (you use remotes for getting patches locally if needed).

                              I think what is important is to have a standardized workflow, and not a proprietary one pushed by GitHub. Having a client in a terminal for patch reviews and some kind of tool to automate rebases and complicated tasks (Git is difficult to use well after all) would be a good compromise to using emails (if it’s just for transport, you don’t need to know that email is or isn’t used). Then this could be applied to GitLab, GitHub, or anything.

                              1. 1

                                Once you have a reasonable volume of pull requests the branches of those pull requests get outdated quickly meaning they have to be rebased before merging or every change will have an extra merge commit in the history.

                                And why are merge commits bad again?

                                1. 9

                                  For feature branches a merge commit that updates against the default branch is just noise in the commit history. This is especially bad if the branch needed to be updated multiple times. In my opinion it is always better to rebase against the default branch to keep the commit history clean. Rebasing before a merge is often good practice anyways, e.g. to squash commits or rewrite commit messages.

                                  1. 2

                                    Indeed, I consider a feature branch being merged into a main branch without a merge commit to be an antipatten that makes the history less useful.

                                    1. 5

                                      This is not about the merge commit of the feature in main, its about merge requests in the feature branch when updating against main.

                                      1. 1

                                        Oh, I see. Yeah, I usually treat feature branches as roughly a patch series so keep merges out of that particular kind of flow, personally.

                                      2. 3

                                        The history should capture as much of the human process as possible without also encoding the details of how git creates that history.

                                        Thus, rebases and not merge commits.

                                        1. 1

                                          If you really want to keep track of merges, you can use git rebase and then git merge --no-ff.

                                          If a single feature may be developed and integrated progressively, having merge commits will add a lot of useless commits in the history, it’s an aesthetic choice that’s all.

                                      3. 1

                                        Haven’t really used any of both workflows up to now, because I don’t have much collaboration in my projects. But what sounds immediately nice to me: If you need to update your local branch to the latest state of master you can actually rebase your local branch, because it may exist only locally. With a pull request approach the feature branch must have been published (e.g. to Github) and rebasing is usually a no-no on published branches.

                                        1. 8

                                          Rebasing is a no-no on shared branches. Force pushing to PRs is routine on GitHub. Myself and the hundreds of contributors I’ve interacted with have been doing it for years with few problems if any.

                                          Actually I find more problems occur when folks don’t rebase and don’t keep history clean. Because then I have to do it before merging. This can get nasty if they’ve merged master into the branch. Which presumably is only done because people have the misconception that rebasing should never be published. But this actually just leads to more problems.

                                          If you’re sharing a branch with others, then yes, it’s poor form to rebase.

                                          1. 1

                                            I see, and by “shared branches” you mean write-shared? Because I would have considered every branch published on the web a shared branch, because somebody could already have downloaded it.

                                            I guess this then needs some concept of how much “shared” a branch is. Because otherwise it would be totally OK if I rewrote the history of any master branch to which only I have write access. Which seems a bit weird to me. If there is a common agreement that forked branches (used to create pull requests) are OK to be rebased, that’s OK by me. I’m not an Github expert, but I don’t see that there is someway a marker on forks that says “This fork is only used to create pull request, please don’t clone it, it can be rebased at any time”.

                                            1. 1

                                              If there is a common agreement that forked branches (used to create pull requests) are OK to be rebased, that’s OK by me.

                                              Yes, that is exactly the case. Most PRs don’t come from the master branch of a forked repo, and unless a branch is specifically advertised, folks generally don’t go around using non-master branches.

                                              The sharing aspect is the opposite for me. Branches that aren’t shared simply have no marker at all. It’s the shared branches that do. master is marked by convention, and if other branches are relevant (say release branches), then those are likely mentioned in the README. That covers most cases.

                                              And yes, it’s not about “write” shared. Rewriting history will mess up read only users too by requiring them to git reset --hard their local copy to synchronize.

                                              Yeah, it’s two different ways of using git branches. But I don’t think I’ve ever seen anyone mix these up before. I’ve only ever seen people initially not rewrite history in a PR because they thought you weren’t supposed to push rewritten history.

                                              As usual, the core git tooling does little to make this workflow clear.

                                        2. 1

                                          Great read, I didn’t know much about git send-email before reading this full disclosure.

                                          We use Github and Gitlab at work - so I’m very much used to that style of pull-request workflow. Ever since Github’s CLI gh went v1.0 it has been very pleasant to use.

                                          It can now inspect PR’s locally, merge them (with choice of merge type), and open PRs all from the CLI (and much more of course). A feature I find myself using a lot is the switch -w to open the current PR or repo in your browser, it’s super handy! I find myself reaching for gh for most PRs at least to give it a once-over before deciding to pop it open in a browser to actually review it.

                                          1. 1

                                            Very good summary, with concrete examples, thanks for posting.

                                            1. 1

                                              If you are regularly managing different patch series and making revisions, U-Boot has a tool called patman for assisting. I organize/send all my series for Linux and U-Boot using it.