10 ms·
Things I know about Git commits
- lucasoshiro 2y agoIf 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 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 https://news.ycombinator.com/item?id=40840572
- fmorel 2y agoThe 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.
- alganet 2y agoTo 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.
- lucasoshiro 2y agoI 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 https://news.ycombinator.com/item?id=39877637
- PaulDavisThe1st 2y agoSee 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.
- ufo 2y agoCould you please give a concrete example of how to use funcname? I tried looking in the man page and didn't get it.
- deleted 2y ago[deleted]
- PaulDavisThe1st 2y agoI 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
- lucasoshiro 2y agoThanks! I'll check it and I'll update my article with that!
- vbezhenar 2y agoI'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.
- rudasn 2y agoGood 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.
- RadiozRadioz 2y agoWell, 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.
- lucasoshiro 2y ago> 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.
- metadat 2y ago> 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.
- jcoder 2y agoNot 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).
- epage 2y agoThe 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 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.
- yerdoingitwrong 2y agoThe 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.
- dakiol 2y agoDepends. 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.
- jraph 2y agoThe 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.
- karmarepellent 2y agoI 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.
- anyfoo 2y ago`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.
- khana 2y ago[dead]
- compressedgas 2y agoI'd also recommend turning off reflog expiration with: gc.reflogexpire=never gc.reflogexpireunreachable=never
- idoubtit 2y agoOver 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.
- r-s 2y ago> 58. Trying to police commit history is going to be painful This has been my experience. Very painful
- khana 2y agoand the winner: Do the work up front to make your history atomic
- donatj 2y ago> 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 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.
- jimmaswell 2y agoI 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.
- Zambyte 2y agoOr 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?
- jimmaswell 2y agoI 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.
- jenadine 2y agoBoth 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.
- osigurdson 2y ago>> 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.
- dougthesnails 2y agoOr learn to rebase those crap commits into coherent ones.
- turboponyy 2y agoYou realize that commits can be changed, right?
- osigurdson 2y agoOf course. However, refactoring N crap commits into M atomic commits where M != 1 is non-trivial. My point is about atomic commits, not git.
- dougthesnails 2y agoBe still my heart.
- deleted 2y ago[deleted]
- jenadine 2y agoIt 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.
- jonathanlydall 2y agoI 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.
- philwelch 2y ago> 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.
- usr1106 2y agoI 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.
- at_a_remove 2y agoAh, 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.
- jraph 2y ago> 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.
- JNRowe 2y ago`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.
- ydant 2y agoThanks 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.
- arcanemachiner 2y ago> - 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).
- deleted 2y ago[deleted]
- g-b-r 2y agoPLEASE, 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).
- philwelch 2y agoI 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.
- g-b-r 2y ago> 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.
- JelteF 2y agoThe 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-controlling-the-default-commit-message-when-merging-a-pull-request/ https://github.blog/changelog/2022-08-23-new-options-for-con...
- praash 2y agoI 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.
- rudasn 2y agoI 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!
- NotBoolean 2y agoThis 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.
- ericrallen 2y agoHaving 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.
- deleted 2y ago[deleted]
- MaryBeew 2y agoFighting 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 )
- cxr 2y ago> 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.
- joshka 2y agoAgreed 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
- SharonDavis 2y ago[dead]