Hacker News new | past | comments | ask | show | jobs | submit login
Things I know about Git commits (jvt.me)
118 points by sea-gold 28 days ago | hide | past | favorite | 101 comments



`git reflog`, which the article prominently mentions, really should be the VERY FIRST thing to teach everyone who is learning git.

If you don't know about it, it is well worth checking it out now.

It is your one ticket to getting to whatever previous, good (or bad!) state you were at any point before[1]. The only thing it cannot help you recover is locally made changes that you never committed to anything at any point, and have since locally deleted. This is surprisingly rare, at least for me, as I just tend to `git stash` stuff I don't want anymore.

With `git reflog` in your backpocket, you can rebase, merge, branch, delete branches, cherry-pick, rewrite history, whatever, all to your heart's content. `git reflog` keeps a journal of every single action, and tells you the HEAD before and after each action, which you can then simply checkout or `reset --hard` your branch to.

I never even use any arguments with it, I literally just `git reflog`.

[1] Unless garbage collection has deleted the commit you were pointing to, I guess, but I've never had to use `git reflog` that far in the future.


Over the last decade, I think I've only used `reflog` twice. The only case I remember clearly was to help a co-worker that had created a local mess, starting with a `git pull` (meaning a merge) on the wrong branch then piling onto that.

If you use Git in a terminal, a much simpler alternative to the reflog is having the commit hash in the prompt. Then comparing/reverting to a previous state just requires scrolling the terminal to find the commit id. It's much easier to read than the reflog. With the help of the shell prompt, the terminal can help with the questions "what did I do to get there and how to get out?".

I also think that Git has become much more error-proof. It's been a long time since I've seen anyone lost in their own repository like I'd seen years ago. There are better GUIs. In the command line, modern Git often displays hints, has warnings for some dangerous commands, and sometimes explains how to rollback.


For me, it‘s usually not about somehow „breaking“ my repository so that it‘s in a „weird“ state, but about messed up rebases, filter-branches (or modern equivalents), and other branch manipulations that leave my branches in a now unwanted state.

When working on big projects with many people, multiple release branches, and constant updates to those release branches, there‘s bound to be situations where you try to juggle multiple local branches for the same change(-set) to massage conflicting changes into place, only to after a while go „no, that went bad, let‘s start over“.

Having the commit ID displayed by the prompt is a good idea, and it solves the problem in a similar way. However, I prefer my prompt to be on one line, and it‘s already pretty long. Plus, I often do lots of stuff between git commands, so I‘d have to „hunt“ for the prompts. I need git reflog on average probably about once a month, and just typing „git reflog“ and seeing what git operations I‘ve performed is perfect for me.


I'd also recommend turning off reflog expiration with:

  gc.reflogexpire=never
  gc.reflogexpireunreachable=never


Defaults for each option of anyone is curious:

> gc.reflogexpire

90 days

> gc.reflogexpireunreachable

30 days


I didn‘t know about that. Good idea, thanks.


Even though I find reflog very useful, I don't think it should be the first thing.

What I think that should be one of the first things and most people don't know is written in "What is Git?" chapter from Pro Git: https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3...


> `git reflog`, which the article prominently mentions, really should be the VERY FIRST thing to teach everyone who is learning git.

Top that up with `log` showing all branches at all times (except if you ask otherwise) and you end up pretty much where mercurial is. Detached heads is such nonsense. Git missing phases and obsolescence (to denote if and how history eventually got rewritten) is another.


Oh, I actually make heavy uses of detached heads. The projects I work on frequently require you to look at a „snapshot“ of how the code was at a certain time when diagnosing issues, and it‘s good to be able to „look without touch“, i.e. being able to check out a specific state without it cluttering up my branches (though honestly, they‘re pretty cluttered already).


Yup, navigating history and checking-out commits at will is VCS ground-level. It's mind-blowing that git managed to make it unnecessarily complex by distinguishing "commits" from "commits with a label on them" (aka. branches), and putting in-your-face warnings when generating new commits in the former case (whereas the DAG itself doesn't care).


I agree!


I'm creating local tmp1 tmp2 branches before I'm doing anything sketchy. Branches will keep the commit visible and I can always return to the previous state if necessary. Tags would be more appropriate, I guess, I just got used to branches more.


You can see „git reflog“ as a sort of automatic tmp-branch creation at every step. Of course your way works as well, and I tend to do the same when I know it‘s getting hairy, but it‘s nice to just be able to do git stuff knowing you can always go back without much precaution.

The only thing I need to remind me to be careful about is, as said, uncommitted changes. With some luck, Time Machine can help for that, but to be safe I practically always stash away changes instead of somehow undoing them.


I prefer to use git from GUI and those usually do not support reflog. I'm aware of it, but that's my tool of the last resort, if I did something very wrong.


I'd replace that with giving someone a link to Git Fix Um[1]

[1]: https://sukima.github.io/GitFixUm/


> People who say "just delete the repo" when things go wrong really frustrate me

YES. Go be a baker or something! If you're going to be a developer you should generally speaking be willing to figure out what's wrong and how to fix it.

Know how your tools work. Bad carpenter what have you...

Also speaking of `git reflog` and such - I still stand by this article I wrote a few years back - https://donatstudios.com/yagni-git-gc

99% of people should just turn automatic `git gc` off. You don't need it. Turn it off and you never have to worry about losing work. It's there, you just have to find it.


Git is an abysmal tool for many (most?) uses of it, but that unfortunately has become "standard". The sheer awfulness of git is witnessed by the amount of posts about it and little consensus on "best practices" (e.g., rebase vs merge).

So, I don't judge, but sympathize with people who just "delete the repo and start from scratch". Unintuitive, user-hostile tools call for heavy-handed solutions.

IME, most people are willing to learn something when they're shown the value for invested effort. That "delete the repo" is standard answer for fixing f*up, tells more about the tool than the people using it. (I.e. it requires disproportionately big investment of time for little value.)


I really don't agree with that. Git is a powerful tool with very few actual downsides, and the unwillingness of some developers to spend an hour learning how it works hurts them in the long-term.

It's like sticking to the text editing feature of your IDE because you can't be bothered to learn how it works. Sure, you _technically_ can do that, but you're losing on everything that makes an IDE useful and probably losing actual days or weeks worth of work because of that.


>the unwillingness of some developers to spend an hour learning how it works hurts them in the long-term

And that's the problem. Because every developer has spent an hour learning how it works by themselves but then each of them in completely different ways, from different sources, on different projects and workflows, some more correct than others, because there's not one single perfect ground truth way of using git in every situation, but git offers one million ways of shooting yourself in the foot once you land on the job, even after you think you learned git in that one hour.

And that IMHO is git's biggest problem: too powerful, too many features, too many ways of doing something, no sane defaults out of the box that everyone can just stick with and start working, too many config variables that you have to tinker with, etc. Case in point, just look at the endless debates in the comments here on what the correct git workflows are wand what the correct config variables are, nobody can agree on anything unanimously on what the right workflow of configs are everyone has their own diverging opinion.


I think you've just described why Git is so popular and literally everywhere.


Something being popular doesn't mean it's universally good everywhere and loved by everyone. Windows and Teams are also popular, almost every company uses them, that doesn't make them good. Diesel ICE cars are also highly popular in Europe even though they're much worse for our air quality and health. Do you see the issue with using popularity as an argument?

I've met many devs who hate git with a passion but they just have to use it because management said so and because evry other workplace now uses it, just like Teams and Windows. Not saying git is bad per se, just pointing out the crater of pitfalls it opens up.


Right but the world is bigger than corporate and yet I don't see anyone choosing anything else for their pet project large or small either. If Git was such a pain to use, wouldn't a lot of open source projects use something else? I know OpenBSD uses CSV, SQLite uses Fossil.. I can't honestly think of anything else non-Git right now that I use (I'm sure I'm missing some).

Years ago when private repositories were still a paid feature on GitHub, you could use Bitbucket, which had them for free, and offered Git and Mercurial. A few years later Bitbucket announced they were removing Mercurial support because "Mercurial usage on Bitbucket is steadily declining, and the percentage of new Bitbucket users choosing Mercurial has fallen to less than 1%".

https://bitbucket.org/blog/sunsetting-mercurial-support-in-b...


>I don't see anyone choosing anything else for their pet project large or small either.

I also don't see anyone else choosing to breathing anything else than oxygen either. It's not like they have so many other options when the job market requires git and most coding tutorials also feature git and schools also use git, so the entire industry decided to use git despite other options existing.

Again, that doesn't mean git is bad or that is loved by everyone or that it's the best. Betamax also lost to VHS despite being technically superior. A lot of victories are won by the lesser product given enough inertia and being at the right time and the right place. Kind of how Windows and SAP got entrenched in the 90s. People and orgs were buying into it because everyone else was also using it so your only choice was to use it too no matter your own opinions on it. What were you gonna do? Piss against the wind and torpedo your hiring prospects by pigeonholing is some other "better" tool that nobody else uses?

I don't remember what VCS I used at my first job in the embedded industry but that one was hands down way better, easier and fool proof compared to git, with a nice GUI long before GIT GUI tools were even remotely good, it just didn't survive there long term because it costed a fuck tonne of money in licensing fees for the org. You can see where this is going, right? When it comes to bean counters, free beats paid every day regardless of most other arguments.


Also smoking was once both popular and everywhere. At least smokers enjoy it, I'm not sure anyone "enjoys" using git.


I'm sure I do.


Instead of turning off the automatic git gc, turn off the reflog expiration with:

  gc.reflogexpire=never
  gc.reflogexpireunreachable=never


I could spend hours of my workday on some uninteresting, irrelevant bullshit because the local repo is fucked, or just delete it and move on to solving actual problems and producing value. The choice is clear.


Or you could spend an hour or so learning to use git (or a git compatible vcs like Jujutsu) and then you never bork your repos, and instead spend your time solving actual problems and producing value.

What kind of pastries do you like?


I can't remember the last time I had to delete a repo, at most I do a hard reset to the head of the main branch. Still don't care and I'm doing well enough getting consistent maximum performance ratings at my job and building things in my own time. Sometimes a problem is not worth addressing, and part of being an effective software engineer on the whole is recognizing those times.


So, contrary to your own point, you did indeed put in some time and learned one of the ways you can fix a "fucked" repo, because it is more convenient to just 'git reset --hard main' than to delete and re-clone.

There are some simple next steps to go from there:

  - notice that you don't have to reset to the main branch, you can put in any branch name
  - it doesn't even have to be a branch name, it can be any kind of reference to a commit
  - 'git reflog' is useful to find out a reference to a commit you recently were on, that you can then give to reset
  - you don't have to use --hard, I personally like using --keep, and sometimes you might want to keep local changes so you don't supply those options at all
  - ...
What you already did is what Zambyte suggested you should do. Of course there is diminishing returns at some point, but that point comes way after 'git commit -am $msg && git push'.


Both points are valid.

But it shouldn't take hours to "fix" a repo in most cases. As you said: git reset.

Anyway, I've been putting some of my repo in very bad states by doing git operation from different unix user that lacked the right permission to do all the writes leaving some corrupted objects and stuff which needs a bit more than just a reset to recover. Then it takes some time to recover, but that's because I also don't want to loose some hours of un-pushed work.

Doing a delete of my repo could have been faster but I'd have lost some temporary branches and squashes and stuff that would also represent some work.

But I think the original point is for people who are not even able to do a git reset.


>> Or you could spend an hour or so learning to use git

This is such nonsense. The git you can learn in an hour gets you exactly to the point where you end up in this "now what?" situation. Furthermore unless you're working through this more regularly than every 6+ months you're not going to remember how to fix it.


> Furthermore unless you're working through this more regularly than every 6+ months you're not going to remember how to fix it.

Take notes.


I have never deleted a repo because it's messed up. In the early days understanding what was wrong was sometimes challenging. But once I learned it it's just routine to clean it up. I do occasionally search stuff from my reflog or trial branches from years ago, no way I want to lose that opportunity.

One needs to learn full branch names and how the abbreviations used in daily life really work. A local branch called origin/foo can be confusing, especially after being pushed. And of course one needs to understanding the concept of remote branches in the first place, they are not really remote, typical poor git terminology.

For mass mess-ups in the work tree git status -s | grep ... oneliners are your friend.


Or you could actually learn git once and enjoy using a powerful tool without experiencing any of this friction. If you understand git you'll just know what to do when some weird thing happens.


I haven’t done that since my junior days. Do people really do this? I know Git’s UX is bad but wow.


To me, commit messages really shine on file histories and `git blame`.

Opening an unknown file and having the option to see all it went through is powerful. The commit messages and history will tell you which files are related, which files change together, why they do, etc.

It's a superpower that a team can cultivate.


I strongly agree.

Git isn't only code sharing that you commit and forget. It is a database of code that tracks what changed, why changed, who changed and when changed.

Want to know why a piece of code exists? Find the commit that introduced it, read the message. If it's not enough, you can search the commit and find the discussion on GitHub/GitLab/etc.

A new bug suddenly appeared? Use git bisect to find what was the commit that introduced it.

Some months ago I posted some tips about using Git as a debugging tool, if you want to read more about it: https://news.ycombinator.com/item?id=39877637


See also:

    git log -L:funcname:file
funcname will be matched after wrapping it in a "function declaration identifying" regexp.

Get the entire history of a given function (as long as it was in <file>). Not a daily driver, but sometimes unimaginably valuable.


Could you please give a concrete example of how to use funcname? I tried looking in the man page and didn't get it.


I work in C++, so I might be looking for the history of

        Session::set_state (XMLNode const & node)
I would write:

        git log -L:set_state:session_state.cc
If I worked in C, and I had this in a file:

        void
        some_function_name (type1_t t1, type2_t t2)
I would write

        git log -L:some_function_name:thefile.cc


Thanks!

I'll check it and I'll update my article with that!


I'm using git history may be one time a year. And even those times might be just of pure curiosity: who's that dumb who did that bug. Basically it's useless for me. So I don't care much about commits. Git for me is a collaboration tool and code backup tool, and that's about it. Nobody will look at my 1-year old commit and I'm not going to look at anyone's 1-year old commit.


> who's that dumb who did that bug

You can find more than that, e.g. what was the context of the introduction of a code, find the discussion about that introduction, what was the situation of the project when the code was introduced, etc. But even if you only want to blame, it is enough to keep a good commit history.

> Nobody will look at my 1-year old commit and I'm not going to look at anyone's 1-year old commit.

If you commit history isn't good no one will. And no one will benefit of using git. And then you don't need to use git.

> Git for me is a collaboration tool and code backup tool, and that's about it.

If you don't see the point of having a commit history, there are other tools that fit it better. For code collaboration, JetBrains' Code With Me and VSCode's CodeTogether. For code backup, Google Drive or Dropbox.


Well, it completely depends on your job and work style. Personally I'm a site reliability engineer, so when something breaks it's an invaluable step to look at the commit history to see what changed, when, how, why, and by whom.

I'm searching through commit histories several times per hour.


Good commit messages can be used in lieu of official documentation, and that makes them veey helpful.

Whether or not relying on git commit messages for source of truth documentation is a good idea is debatable, but personally, when people do it I'm glad they did.


The most effective way I've found to get other people to "write" good commit messages is by changing the "Default commit message" for squash merges on the GitHub repo to "Pull request title and description". [1]

That fixes the "Squashing, when you have 100 crap commits, and then not re-editing the message is a crime" item, because suddenly not re-editing will give you a fairly useful message. This ofcourse assumes the PR description is useful, but I've found it much easier to convince people to write a decent PR description than to write decent commit messages.

[1]: https://github.blog/changelog/2022-08-23-new-options-for-con...


I love giving examples and context in a PR description. Squash-merged PRs can become cumbersome snowballs, but the final commit message should elaborate in proportion.


I also like to include before and after tables, either with stats (eg. perf) or with screenshot with UI changes.

First I head about automatic squash messages, and if they include the whole title and description I should look into it a bit more!


This is what we have resorted to in my team. It was just too difficult to get everyone to keep good commit hygiene and follow a best practice like conventional commits.


Having been through the pain of getting teams to adopt conventional commits a few times, I found that integrating a wizard like commitizen helped folks who were annoyed by commit linting learn and get comfortable with the rules and format so there was less friction when their commit was rejected by the linter.

It also really helps if you can wire up some continuous deployment to automate something tedious like properly incrementing the version number in the semantic version, updating the changelog, and deploy out a new `latest` or `next` tag to the package registry.

Even the most reticent users are often inspired to follow conventional commits once they see the possibilities that open up.


If you want more controversial things about squash, here are two that I posted here last week:

1. "How squash merge can break Git repos with submodules", about a situation where squash merges silently broke a repository: https://news.ycombinator.com/item?id=40846596

2. "Git: please stop squash merging!" giving some technical explanation about what squash merges actually are under the hood and how the misconceptions about Git leads to invalid "pros" about squash merging: https://news.ycombinator.com/item?id=40840572


The first is solvable with a PR check. You can do whatever you want with the submodule on your branch, but if you want it to merge to `main`, then your changes to the submodule have to merged to its `main`. We have a check that makes sure the referenced commits is on `main`, and not older than 10 PRs.


It frighten me how some contributor to my open source repo just don't care about their git history. They do 100 of "crap" commits (author's wording) and merge commits. Sometimes I'd write a comment like: "can you please rebase your branch" and even very senior software engineer are clueless and can't do it even if I give the exact git command i'd use. In the end it's simpler for me to do it myself.

Some developers don't even use git and just use some UI on top.

I wish GitHub would have an interface to do interactive rebase and edit commit messages.


I consider myself very knowledgeable on using Git even though I almost exclusively use it through GUI tools, however my particular GUI wrapper of choice, TortoiseGit on Windows is incredibly powerful. I very regularly do rebasing, squashing, use worktrees extensively, etc.

When I occasionally have to work on Linux or macOS for our Electron based cross platform product, I haven’t yet found a GUI tool I feel comes remotely close to TortoiseGit in terms of advanced features. So much so that if I need to do things like rebasing or dealing with slightly complicated merges, I push first to a branch and then do the Git work on my Windows machine.

I could work out all the Git command line arguments for these advanced use cases, but for something like rebasing with some squashing or skipping, I can’t see how anything except a well designed GUI could be anything except a seriously clunky and much slower experience.

My feeling is that (good) GUIs in general make a lot more sense for Git, instead of having to read the entire manual upfront to know the available tools, the GUI can show relevant options based on context and you don’t get bogged down having to type out/paste commit references and other things into your terminal.

I occasionally use the built in Git tools on VS Code and Visual Studio 2022 (the latter of which only in the last couple of years didn’t completely suck), but generally only for simple pulls, commits and pushes, which is generally more convenient in the IDE than having to switch to TortoiseGit.

Of course a tool is just a tool, if you don’t “get” how Git works, no tool will save you, but I do think TortoiseGit’s rebase UI helped me get to the point where Git “clicked” for me sooner.


> I could work out all the Git command line arguments for these advanced use cases, but for something like rebasing with some squashing or skipping, I can’t see how anything except a well designed GUI could be anything except a seriously clunky and much slower experience.

That’s just an interactive rebase; on the command line it opens a text editor. It’s pretty easy.


magit.


I have nothing against EMacs, but I’ve never used it and have no particular plans to do so while I spend the overwhelming majority of my time on Windows.


FWIW, Emacs and magit works perfectly well on windows (well, as much as git works well on windows). I used it as my main editor during my stint at MS.


> Do the work up front to make your history atomic

Is this saying 1 feature / main "idea" per commit?

Overall this post is gold, but also probably preaching to the choir. IME it's challenging to convert non-believers to the faction of Orthodox Git.

For me, learning the ins and outs of Git felt like uncovering a part of myself which has always been there. Nothing new was created, only revealed.


Not the author, but when I use the phrase I mean each commit accomplishes a single important thing, but also that each commit is complete: it includes necessary tests for example. IMO every commit that lands on `main` must pass the test suite (this means intermediate commits should be squashed into that atomic commit).


The more I've been doing open source maintenance and contributions where there isn't as much context between the code author and reviewer, the more I've been pushing for a little more than this.

- Add tests in a commit *before* the fix. They should pass, showing the behavior before your change. Then, the commit with your change will update the tests. The diff between these commits represents the change in behavior. This helps the author test their tests (I've written tests thinking they covered the relevant case but didn't), the reviewer to more precisely see the change in behavior and comment on it, and the wider community to understand what the PR description is about.

- Where reasonable, find ways to split code changes out of feature / fix commits into refactor commits. Reading a diff top-down doesn't tell you anything; you need to jump around a lot to see how the parts interact. By splitting it up, you can more quickly understand each piece and the series of commits tells a story of how the feature of fix came to be.

- Commits are atomic while PRs tell a story, as long as it doesn't get too big. Refactor are usually leading towards a goal and having them tied together with that goal helps to provide the context to understand it all. However, this has to be balanced with the fact that larger reviews mean more things are missed on each pass and its different things on each pass, causing a lot of "20 rounds of feedback in and I just noticed this major problem".

As an example of these is a recent PR of mine against Cargo: https://github.com/rust-lang/cargo/pull/14239

In particular, the refactors leading up to the final change made it so the actual fix was a one line change. It also linked out to the prior refactors that I split out into separate PRs to keep this one smaller.


I agree, but I usually explain (and do) this from the side of fixing a bug, but where the test suite is currently passing: first commit adds the failing test (shows that it would have caught the error), second commit makes it pass.

Also agree with GP that each commit on master should be passing/deployable/etc., but I don't see why they can't be merge commits of a branch that wasn't like that.


That still interferes with `git bisect`. Make the test pass in history but then make it fail in your working directory and work to get it to pass before committing.


No it doesn't? Only on your unmerged branch anyway, which seems either no big deal or desirable to me.


I absolutely love that testing suggestion - I'd never considered shipping a whole separate commit adding the OLD test first, but having a second commit that then updates that test to illustrate the change in behavior is such an obviously good idea.


> Make sure you review your own code changes

The author says he reviews himself on a GitLab MR / GitHub PL, I rely on two things for this:

- git add -p, which also helps me split stuff in several commits if needed. It bothers me that it doesn't work for new files.

- git difftool dir-diff for changes with several commits

I like that it would work on any git hosting, and that it works locally. And that I can just amend my commits if I see something.


`git add -p` can also work for new files, it just requires you to call `git add --intent-to-add` first. After using -N/--intent-to-add you'll see that the file is registered in the status output, and -p will work exactly how like you expect.

I often find myself spiking things then breaking them back down with -N and repeated `git commit -p` to form a reasonable history. The workflow seems to really suit my mind. However, it does require some testing vigilance if you're manually editing the hunks for clarity on top of simply splitting them up.


Thanks for the hint about `--intent-to-add` / `-N`.

There's constantly new things to learn about git. I use `git add -p` extensively, but never thought to check for an option like that.


> - git add -p, which also helps me split stuff in several commits if needed. It bothers me that it doesn't work for new files.

Lazygit is an amazing tool that can definitely do this (and many other useful things).


Ah, the endless mysteries of git. People say, "It's so simple once you understand the base model." And yet there are these inevitable buts. And somehow, people keep arguing over how to use it, what is the Correct Way. If it were that simple, the One True methodology would be obvious, yet the disagreements continue. Then I ask dumb questions about merging and have yet to hear how the magic happens, just very circular "merging ... merges" answers.

One day I hope to have a positive and comprehensible experience involving git and perhaps even git and another programmer, but that might be too much to ask.


> There needs to be a way to add an annotation[...] to a previous message to correct assumptions

You rarely want to do _just_ this, i.e. call out the bad commit message in question and nothing else; you're generally going to have something to fix because of that "bad assumption", too. You just branch off the old commit, do the needful (read: make the correction to the code), commit it, and then merge that into mainline. It seems like a lot of people fail to consider that a branch merged into mainline does not become immutable; at any point you can check it out and make further changes and then remerge those and do all of this as many times as necessary.

If you really do need to only draw attention to a bad commit message in a past commit and correct the record but nothing else, then you can just "annotate" it with an ordinary merge commit—

1. Check out the old commit that you want to annotate (create a branch there if you want, but it's optional).

2. Merge the mainline into this HEAD/branch, making sure force a merge commit using --no-ff, and write your "annotation" in the commit message.

3. Merge that into the mainline branch.


The most USELESS commit messages are "Fixes #12345 (#23456)". It tells the git log reviewer NOTHING. You shouldn't have to rely on github to understand your project. State the intent of the bug fix in the commit message.


Depends. If the number points to a very well written ticket, that’s fine. We work with Jira and Github and all the bugs/features are explained in Jira tickets. I’m not staying long enough in this company to see them changing from Jira to something else, so I don’t care about the Jira dependence to understand commits.


The git log should still stand on its own. The ticketing platform could get migrated in a way ticket numbers are not kept or old tickets are a bit less convenient to find, or just temporarily down.

When working on the code, it's also very useful to access the history without having to open each ticket. Being able to hover a line, having the message of the commit which last changed it, and be able to say "ah ok, it was for this" is quite useful.

> I’m not staying long enough in this company to see them changing from Jira to something else, so I don’t care about the Jira dependence to understand commits

Isn't this a terrible argument in favor of "Fixes NNN" commits? Someone who care about the longevity of a versioned thing should care. If you don't care anyway, nothing matters much.


I don't know about the "git log should stand on its own". Chances are that when you finally migrate to another ticketing system and the ticket numbers in your commits "break" or become meaningless, you do not care much about that old history anyway.

And even if someone is interested in an old commit that contains a ticket number for a ticketing system that does not exist anymore, the commit itself (the code changes, not the message) tell the story as well, just not in prose.


It's pretty common with configuration or infrastructure as code that a blame brings me to a commit from 5-6 years previous, where I wish to understand why the authors at the time made a specific decision.

That is more than enough time to change ticketing system, wiki platforms, or collaborative chat services.


Fair enough, I did not think about the IaC space when I wrote the comment. And I can absolutely see how a blame could take you to commits from a few years back.

I was only thinking about the application code space where elaborate code comments are definitely more common.


Having had to dig through git history across ticketing system migrations, I agree with grand parent.


> Being able to hover a line, having the message of the commit which last changed it, and be able to say "ah ok, it was for this" is quite useful.

Honestly, this just sounds like we need better integrations with JIRA into dev tools. I'm not going to rewrite tickets in commits / PRs. That ticket has its own history, linked tickets, acceptance criteria, epics, related bug tickets, etc.


Copy-pasting the title of the ticket into the commit title is not much. Or editing the title of the ticket at commit time when everything is clearer.

But indeed, you could imagine some script that fetches the ticket title / content from the ticket number and commits. Nice weekend or hackaton project.


Well written GitHub issues and PRs that you can reference in your git commit also don't save you from commenting code. I mean please do not reference an issue in a code comments, but describing to other people what a function in general does goes a long way to build understanding.

For new contributors it's probably also more useful to see the latest snapshot of the code base and code comments than having to check a git log in order to find out why a function would be written in the way it is.


I'll absolutely reference an issue number in a comment (with some context comments as well) in cases where it makes sense.

Sometimes you need to go back and read through a lot of context understanding why a block of code does what it does, and it's a lot more efficient for the rest of the time to have a quick reference to the full explanation rather than pages of comments giving that context.


Agreed. For PR commits, appending the PR number (e.g. `#8`) to the short message is fine, but the short message should still contain a summary of changes. For issues, having something like "Fixed #8" in the commit message body is picked up by forges like GitHub.


PLEASE, recognize that "atomic" commits as the author defines them (basically whole features), will actually jumble up a large part of the diff, however much advanced your diff program is, making verifying the changes a lot harder..!

If you like to see chains of commits each with a complete feature, just remember that merge commits are commits as well!

Sure, rebase a feature branch before merging it, but then merge it with a merge commit ! (merge --no-ff)

That way you'll have both your "atomic commits", and actually atomic commits, that is commits with changes that any diff program will be able to highlight correctly. Verification will be extremely easier, but you'll retain the ability to browse the history at a higher abstraction level (either use any decent graphical git browser, or simply --first-parent).


I prefer the exact opposite approach personally: no merge commits, only rebases and fast-forward merges to master. Of course I never merge more than a handful of commits to master at a time—almost always just one—and if it’s more than one, it’s specifically because the diff is more understandable broken apart that way.

Though to be honest I am not sure what you mean by “jumbled” diffs. If you’re pushing a bunch of intermediary commits that don’t make sense on their own, don’t; that’s what interactive rebase is for. If you’re seeing jumbled diffs it might be specifically because you’re relying on merge commits instead of rebasing and fast-forwarding; if you consistently and diligently rebase that isn’t a problem.


> I prefer the exact opposite approach personally: no merge commits, only rebases and fast-forward merges to master

I know that many do, unfortunately.

It's a legacy of how git was used initially, I guess, and of the use of e-mail for sending Linux patches

> Though to be honest I am not sure what you mean by “jumbled” diffs.

Simple modifications such as code moved or indendation changes wil usually only be recognized by diff programs if they're on their own, without other changes included.

It's unfortunate, but since that if the state of things, adapting to it by making small commits will make reviews massively simpler.


> Simple modifications such as code moved or indendation changes wil usually only be recognized by diff programs if they're on their own, without other changes included.

Yeah, those are some of the situations where I will push multiple commits. Though indentation changes are something I prefer to avoid by using autoformatters.


> Though indentation changes are something I prefer to avoid by using autoformatters.

Well when you extract a function, add an if, loop, or do any number of other things, you can't avoid changing the indentation (unless you want to leave a mess)


Sure, and if you also change the logic inside that loop, I don’t think the combined diff ends up being “jumbled” or misleading at all. Also you can hide whitespace changes.


Even with hiding whitespace changes, the differences often don't get recognized correctly.

Rather then misleading, the diffs are much harder to check, instead of showing that only white space changed (or in general, rather than highlighting only the actual thing that was changed).

Basically, it's little additional work which guarantees simpler reviews for everyone, I think it's warranted


I agree with most of the items on the list. But some are too short to understand what they mean or they are really "It depends".

The most important point for me is that the same tool is used for 2 purposes: Keeping track of quick trial and error experiments so that you can return to the best one once you have made up your mind. And producing a readable story of self-contained atomic commits telling a story to the reviewer and yourself weeks or years later.

I hate myself every time when I don't get the context switch right between those 2 modes of operation. Or just don't do the second phase because I first need fo fix a bug and will continue with the current branch later.


Fighting to restore love and peace in my relationship was so frustrating until I saw a video of a lady's testimony talking about how are marriage was restored. It was a whole experience I never thought could have been possible. My partner and I are happily reunited in Love and harmony, All thanks to priest Mandla for the Help he rendered to me and my family. You can still save your marriage or relationship, email: ( supremacylovespell01 @ gmail. com )


Agreed with this pretty much 100%. I'd add to the list:

- oh my zsh git shortcuts are great

- git-extras (especially git-brv for when you're an open source library maintainer)

- pushing to PR submitter's branches to clean up a PR ready for merge is a good skill to know


> 58. Trying to police commit history is going to be painful

This has been my experience. Very painful


>> Squashing is better than 100 crap commits

Unless your work is trivial, you will have crap commits. Have discipline but don't insist on working on trivial things just so your commits appear logical without rework.


Or learn to rebase those crap commits into coherent ones.


You realize that commits can be changed, right?


Of course. However, refactoring N crap commits into M atomic commits where M != 1 is non-trivial.

My point is about atomic commits, not git.


Be still my heart.


and the winner: Do the work up front to make your history atomic




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact