Build1 publisher2 min readPublished
Four keys in lazygit's merge panel settle on three different commit graphs
A dev.to walkthrough pressed M once per option in a throwaway repo and read the graph after each. The default fast-forwards when the target branch has not moved and writes a merge commit when it has.
The Engineer · Build desk
What happened
- In lazygit 0.62.2, putting the cursor on a source branch in the branches panel and pressing M opens a panel titled Merge with four options, bound to m, n, s and S.
- The author tested them in a throwaway repo with three commits on a feature branch, reading git log --oneline --graph after each option and running git reset --hard HEAD@{1} before the next.
- The n option always writes a merge commit with two parents, the previous tip of main and the tip of feature, and the three feature commits survive as themselves underneath it.
- Both squash options collapse the branch's three commits into one commit on the target, and that one commit is all the target records.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision The key you press decides whether git log --first-parent can list the repo later as one entry per landed branch, because that listing needs the merge commits to exist.
- constraint Once a squash lands, the step-by-step record survives only where the source branch still exists; the target keeps only the squashed commit.
- capability The s option hands over the squashed change staged and uncommitted, so a person writes the message on the only commit the target will keep.
The four menu entries settle on three end states: a straight line of commits, a merge commit sitting on main, or one squashed commit on main [1]. Each option runs the same merge, and what differs is the graph left behind [18]. The default, m, accounts for two of the three [4][5].
That is because m reads the state of the target branch at the moment you press it. If main has not moved since feature was cut, main's pointer slides up to feature's tip and no new commit is created [4]. If main has moved on, git cannot fast-forward and writes a merge commit instead, the same shape the n option always produces [5]. The post recommends m for a really short-lived branch where the target did not move, and says that the moment the target has its own commits you get the merge-commit graph anyway [6].
In the fast-forward case, the history does not name the branch. The three commits sit in the line, and according to the post a reader of that line cannot tell they arrived together as one reviewed unit [7]. The merge commit has its own cost: the graph gains merge points, and the post reports that anything assuming a linear history, some revert flows among them, gets slightly more work to do [10].
Between the two squash options, the difference is who writes the message. After s, the target's log is unchanged from before the merge, and the squashed change sits in the working tree, staged, until you commit it yourself [13]. After S, the target's history is the squash commit above the initial commit [12]. The author says s is the option they reach for when the commit message matters [19]. On what both squash options give up: "The trade is: you gain a clean, one-commit-per-change history, but you lose the record of the journey," the author wrote [14].
What to watch
- Whether lazygit keeps m as the default Merge menu entry in releases after 0.62.2, the version tested here.
- Whether teams that squash start keeping the source branch's intermediate commits somewhere, since only the squashed commit lands on the target.
- Whether the revert tooling in your setup handles two-parent commits, the cost the post attaches to the n option.