4 ms·
There are two solutions that come to my mind, both are more by convention: 1. Always use merge commits (--no-ff) a la git flow, and leave the branch name in th
by ISO-morphism 5y ago
There are two solutions that come to my mind, both are more by convention:
1. Always use merge commits (--no-ff) a la git flow, and leave the branch name in the merge commit. That doesn't get you the branch name on the commit, but it should help identify the branches.
2. Use a pre-commit hook to put the branch name or bug tracker ID at the bottom of the commit message. There are some tools built around this, I've done it at $DAYJOB with a custom python script I manually copy around into `.git/hooks/pre-commit`.
- rezonant 5y agoGood solutions. FF/rebase are very nice, but I've seen devs sleuth into a squashed PR commit, find the PR the features came from and read it on GH, and that's powerful. I saw a new dev do this recently. They dug into the original summary of the changes from the dev (for a PR that landed 6 months before they joined) and the flow of conversation around the work. They had insights into the decisions the team made around the feature as it was developed. The PR linked to the product artifacts that led to the work, so they had the business context. They nailed the implementation, first time :-) There's a nice benefit to doing merge/squash and providing a link to a set of context around the specific set of commits, not just a contextless line of commits, as clean as it may be.
- kazinator 5y agoGit merge does something pretty awful; it takes multiple changes and turns them into a single patch bomb in the destination branch. What if the branch has 17 commits, the 9th of which introduces a regression? Moreover, suppose that the 9th commit of the original branch didn't exhibit the regression; rather, its change had that effect when it was merged into master. You need all 17 commits, in their rebased versions, on master, so you can search through their history (e.g. with git bisect) and discover that the 9th one broke it. Rebase is the correct thing: it calculates a new sequence of commits that are individually merged, and retained as separate commits that you can dig through in the new branch. What's missing is this: the rebase of an entire branch into a new branch should record a second commit parent (for the final commit of the operation), pointing to the final commit of the original branch. Like this: X-Y-Z--<< branch / -A-B-C-D-E--<< master rebase it: X-Y-Z--<< branch / \___ / \ -A-B-C-D-E-X'-Y'-Z'---<< master where X', Y', Z' are the rebased versions of X, Y, Z. A regular git rebase is missing that second parent link from Z' to Z. You just get this: X-Y-Z--<< branch / / -A-B-C-D-E-X'-Y'-Z'---<< master The only way you can identify that Z' was cherry-picked from Z is by clues in the commit message: identical commit message text, or something like a Gerrit Change-Id. Possibly, each cherry-picked commit should have the original as its parent: X-Y-Z--<< branch / \_\_\___ / \ \ \ -A-B-C-D-E-X'-Y'-Z'---<< master now that is almost like iterating over the branch and doing a commit-by-commit merge. At first we pretend that the branch is just X, and merge it to get X'. Then we merge Y', and then Z'. We never merge a sequence of two or more commits into one. If you do that, you have both: nobody can say you're not merging, but you have the effect of a rebase. A rebase (cherry-pick) is a kid of merge: of one commit (at a time), without recording all the parents. A case can be made for rebasing commit-at-at-time using merge. (Not for private work, obviously; just already published, permanent history). The nice thing about rebase is that it doesn't introduce the crufty parentage, which makes it ideal for rearranging unpublished history and then presenting a clutter-free end result.
- preseinger 5y ago> What if the branch has 17 commits, the 9th of which introduces a regression? Moreover, suppose that the 9th commit of the original branch didn't exhibit the regression; rather, its change had that effect when it was merged into master. For some developers, the commit is the cohesive unit of change. For others, the PR as a whole is the cohesive unit of change. I fall into the second group. The ninth commit of my branch is meaningless -- it's only the branch as a whole which can be understood as a single coherent thing. Squash merges reflect and support my methodology.
- Spivak 5y agoI also have found myself in a shop that uses this flow, and don't get me wrong, it works pretty darn well, but it's also just turns PRs/branches into commits and is effectively a single-branch linear workflow with extra steps. It's the closest thing to not using git that exists.
- preseinger 5y ago> it's also just turns PRs/branches into commits and is effectively a single-branch linear workflow Yes! This is ideal.
- w-j-w 5y agoThis is Continuous Integration or Trunk Based development, and it often shows up in surveys as being a very effective tactic.
- hn_throwaway_99 5y ago> It's the closest thing to not using git that exists. Totally disagree, because the whole reason for this is to support multiple developers working simultaneously of the same master branch. That is, sure, master may just be a linear history of commits, but at any specific point in time there may be 10 feature branches off master, each from a different branch point.
- kazinator 5y ago
- superbatfish 5y agoAs a variant of option 2, could one create a new tag at the pre-merge commit?
- Katharsas 5y agoWe do exactly that. If you are on the main branch and merge "feature/my-feature", we use an bash script to create a annotated tag called "integrated/my-feature" which replaces the feature branch. So on our clients it looks like we have a tag folder "integrated" with all previous branch names.