Live data from Hacker News

The git history command

lalitm.com

321–330 of 330 posts

Re: The git history command

#321

Earlier quoted context omitted.

I've often found that many problems when working in teams can be traced back to `rebase`. I understand the benefits, but if you're already working on a team where history is not used in any serious way, then you cut out a lot of foot-guns by only using `merge`.

Except the "merge mess" footgun. I got into training people in Git (I now do it for O'Reilly) because I worked with 12 teams that merged _everything_ into sub-branches. The result was that the `git log --oneline` command resulted in screensful of just pipes. My initial training goal in training was getting my students to understand a rebase to avoid that mess.

Can you point to your course in O'Reilly catalogue please?

Re: The git history command

#322

Earlier quoted context omitted.

> How would you identify the commit that broke the test? You're asking how to use bisect. You start with a range of commits you picked. All that bisect does is help you search for a commit within that range that introduces a regression. The responsibility to specify which commits you cover is yours, not the tool.

And then bisect fails because it finds one of the many commits that broke the test before the actual regression

> And then bisect fails because it finds one of the many commits that broke the test before the actual regression

And that's ok. You skip the commit and move on with your life.

Re: The git history command

#323

Earlier quoted context omitted.

My observation has been that those who have never learned Git properly -- disregarding for a moment the issue with what "properly" means here -- just don't think they need to, sticking to very simple workflows that produce linear graphs featuring squash-rebased work throughout. Because they don't know Git's fundamental model (including what you'd think was the obligatory piece of information that commits are essentia…

> creating a branch starting at the problematic commit Code always lives in a context, and when you're fixing a problem that exists in top-of-main the context of the fix needs to be top-of-main, not some commit way back in history. Also if you do it that way, you'd better hope that no later commit also touches that same line. > I then get people coming to me and complaining they can't merge A team needs to agree on g…

It depends on how much the code has changed, how easy it is to test old releases, how far back you need to merge the fix... "Cherry picking from the top of tree" is the most common workflow but git itself uses "merge the same topic branch in all trees".

Re: The git history command

#324

Earlier quoted context omitted.

you can use git switch to change branches

I know, I use switch and restore now (for the most part). I'm explaining how knowing the internals does help understand the 2 use-cases being originally implemented via 1 command, i.e., checkout. The post I was responding to said the checkout case ran counter to the idea that knowing the internals helps use the commands, when it's actually a pretty standard case where it does help.

Everyone learns git checkout real quick after you lose that uncommitted change. I learned the hard way.

Re: The git history command

#325

I was uncomfortable with git until I read (the first 3 chapters of) the pro git book ( free here : https://git-scm.com/book/en/v2 ). It provides a great mental model of how git works under the hood. The UI of git - for better or worse - directly reflects its internals. And when I understood them, everything clicked into place.

Git is not nearly as confusing as people make it out to be. They just never take the few hours it takes to understand it. Which is a sad state of affairs for such an essential tool in the belt of any software engineer. git commit -am “Changes” just does not cut it, if you call yourself a professional.

As he sits on his thrown looking down on others.

If what you said was true, https://ohshitgit.com/ wouldn't exist.

Re: The git history command

#326

Earlier quoted context omitted.

Ok but the final outcome, most of the time, is a linear graph unless you're maintaining extremely long-lived branches for some reason. Setting practices so that linear graph will be easy to understand in history is still a good idea, no? I'm not religious about squash-merge on master but when I look at master's history, I'd expect each individual commit to have a good message and be releasable.

My philosophy is that if you could've written your patch on current master, you should rebase it, but if there's any divergence that requires actual merging, then you cannot discard the divergence and merge from history because that will mess up history. You can only discard that if you do an actual rebase onto master, fixing up bugs and ensuring each commit that you are pushing compiles and runs by itself - a "fix c…

Ok, I admit arguing about Git's merits, best practices, workflows and so on, can be hard online like this, not the least because I have limited amount of time I can invest in this admittedly very interesting to me discussion, so it requires upfront reasoning (in addition to the typing, which is relatively cheap) but I feel obliged to respond.

First, I agree commits shouldn't store broken snapshots -- if that's what you mean -- code that doesn't compile or outright is _known_ (as opposed to omissions that weren't caught otherwise and made it into the commit) to be broken, not run, produce runtime/type-checking errors, miss dependencies/assets etc. Not everyone would agree -- in our shop people routinely commit "stuff" for reasons they don't disclose that also remain unexplained to me (not having any explanations my way), and then more stuff on top of that. At some point they tag one of these commits as "v2.0.0" triggering automation that releases a package, often broken. Then they scramble for "v2.0.1" etc. I find all of it tedious and unnecessary -- my best practices would rather be to run automation that does checking and sufficient filtering for "bullshit code" as early as possible -- at the "pre-commit" stage, so only whatever passes through that ends up being committed in the first place. If it yet runs into regressions or other problems in production, I fix (re-triggering all the checking again) and release a strictly patch version -- unless fixing was impossible without breaking compatibility in which case it may be a minor or even a major version bump. I do tag commits, too, obviously. But in principle every commit is "production", the difference is not every commit makes up a _release_ (implying to the general public / intended audience).

Regarding rebasing -- that depends on what you mean exactly -- there's different ways to rebase -- you can squash, auto-squash and/or apply fix-ups, or you can just transplant stuff -- when you say "you should rebase" and "patch on current master", what do you mean? Github-driven projects often don't permit pushing `master` without a PR, so a rebase upfront would have been necessary if the author for some reason is not on a branch [other than `master`].

"Actual merging" -- do you mean merge commits as opposed to fast-forward merging which doesn't produce an additional commit? If the latter, what does "merge from history" mean, again? You just need to produce a working snapshot, expressing it with a commit with N parents, there's no more to it. It's fixing of the merge conflict that requires you to understand the graph, the resulting commit is just the period at the end of a long sentence, so to speak.

Anyway, I really missed the point you were trying to express with your first paragraph, I am sorry. Do elaborate, please.

Bisecting also _benefits_ from non-linear "actual development" graphs -- apart from commits that don't feature broken code committed haphazardly for "reasons" (some people use Git as backup, that I know for a fact) -- since they don't hide the work (one of the reasons I prefer raw graphs over squash-merged "polished" stuff).

One thing I should mention in any case is that I do find slicing work into atomic commits often very tedious and counter to what Git is supposed to sell (distributed friction-free concurrent versioning). Because my brain doesn't always work in terms of concepts aligned with Git's -- I routinely may start with one feature fix, on some branch, then discover N related issues, fix those because they're in front of my face then and there, end up with an unreadable diff I can't cleanly add in chunks, etc. None of that is facilitated by Git in any more capacity than just being a scalpel. I don't always want to cut down a tree with a scalpel, obviously.

Pijul, an alternative VCS, uses this nice patch theory guaranteeing you can "apply" commits in any order, compositing your changes essentially -- a feature is just some baseline that is added N commits (in any order, like the mathematical `+` operator). That way you don't have to rebase anything because parenthood doesn't break merging -- if you fix a bug with a patch in Pijul, you can store it once and count on it being applicable to any snapshot made later, even if the result isn't visible -- unlike with Git where rebasing some old commit will abort and ask you to fix a conflict because Git cannot continue.

Re: The git history command

#327
post #143

I was uncomfortable with git until I read (the first 3 chapters of) the pro git book ( free here : https://git-scm.com/book/en/v2 ). It provides a great mental model of how git works under the hood. The UI of git - for better or worse - directly reflects its internals. And when I understood them, everything clicked into place.

Same here. The git commands were confusing to me until I actually saw a Linus video on youtube explaining how the git data structures worked under the hood. It was dead simple, and one could easily mentally map the tools' functions onto how they operated on the data structures. Once I understood that, as you said, everything clicked into place. Somehow the "higher level abstractions" that git tries to do makes the th…

Not Linus, this is Randal Schwartz, but this might be the video you're thinking of?

https://www.youtube.com/watch?v=8dhZ9BXQgc4

Re: The git history command

#328

Earlier quoted context omitted.

That breaks git bisect.

Squash all your temporary commits before you push.

No, you don't commit trash to a public branch, EVER, if you can help it. Your commits are as perfect as you can make them, and that does not mean squashed in a trash compactor. That means one logical idea per commit, compiles and works as perfectly as you can make it. Use stgit, and this is easy. You do not break git bisect. No need to squash your trash in a trash compactor. Your standards are lower than mine, not higher.

Re: The git history command

#329
post #99
post #98

TIL, thx :-) somewhat related Q: how do you give two files the same ancestor? so git log will for each show the history to the beginnings of the originally unsplit file? useful for splitting large files.

That's not possible, because files don't have ancestors in git. Each commit's tree is tracked independently and copy/move is just something that's detected via heuristics.

I meanwhile understood that you can commit a copy of a file and then edit both, and then the ancestry tracking options to git log resolve the two split parts ancestry just fine.

Re: The git history command

#330

Earlier quoted context omitted.

Except the "merge mess" footgun. I got into training people in Git (I now do it for O'Reilly) because I worked with 12 teams that merged _everything_ into sub-branches. The result was that the `git log --oneline` command resulted in screensful of just pipes. My initial training goal in training was getting my students to understand a rebase to avoid that mess.

Can you point to your course in O'Reilly catalogue please?

https://learning.oreilly.com/live-events/git-clinic/07901450...
Post reply on HN