ZH version is available. Content is displayed in original English for accuracy.
Advertisement
Advertisement
⚡ Community Insights
Discussion Sentiment
43% Positive
Analyzed from 2141 words in the discussion.
Trending Topics
#git#commit#rebase#branch#history#commits#fix#feature#should#update

Discussion (67 Comments)Read Original on HackerNews
I violently disagree with this.
At a minimum, when I review PRs I look at the commit history to understand what's up. If the path that was taken to commit this is full of "oops" and "fix" messages, it's an immediate reject for me. The commits tell the story and it's a kindness to your human reviewers to not make them work harder to understand the point you're trying to get across.
great way to encourage people to rebase then!
Straight from the git-log, maybe not, but sometimes you see code that makes you wonder how it came to be and it can help a lot to see it in context of the commit that introduced it. That'd be less helpful if that commit were some huge thing making lots of different changes at once.
> commits around it to figure out why that change was even made.
A commit should be such that the message can articulate the why.
Edit: thanks guys, that's very useful knowledge! Could have saved me many times in the past
Figure out a command to test it, a known-good sha and a known-bad sha, and it will binary search its way through the history to find the commit that introduced the failure.
I do, regularly! In a repository where care has been taken, it can be super valuable when tracking down a bug or regression, and understanding the intent of the author
Beyond the archival benefits, I've found plenty of bugs by going back through my "wip" commits and creating a sane history from them.
`git rebase --abort` exists. One can also set a tag or something before doing the rebase, do whatever, then `git reset --hard $set_tag` to go back. Nothing to be scared of. Not like the prior state is lost.
I've almost never needed to run `get reset before-rebase`. But I have often done `git log -p before-rebase` and compared that to the post-rebase state of the branch, to ensure that the merge-conflict resolution(s) that came up during the rebase haven't accidentally introduced an unintended change.
`git tag -f` to move a tag.
Personally, I just do `git show` when I'm feeling cautious, but I can generally just scroll up to find the last `git commit` I did with the hash in the output. `git reflog` should also have record of it, so everything else is kind of extra.
I'm reading that to mean that when I use `git rebase --update-refs` in this situation, where I've currently checked out `D` and update `B` to `B'`:
I'll end up with this state, where `E` remains untouched? (EDIT: Originally I had `E` point to `B'`, which doesn't make sense)If I use `git history fixup`, it would also update `E` and end up with this?
If that's the case, is there a way to get `git rebase` to have the same behavior? I've got decades of `git rebase` burned into my fingers at this point.Can't, because a commit's hash takes into account the parent hashes.
Haven't used --update-refs, but reading it, it should result in your third graph. So,
> is there a way to get `git rebase` to have the same behavior?
is already the case.
I don't think it does. I tried locally:
And ended up with this graph (`git log --graph --all`) Replacing the `git commit -m 'fix b'; git rebase -i --root --update-refs` with `git history fixup HEAD~` produces what I'd like:EDIT: Yeah, this seems to be it. `git branch b` on b, then `git rebase -i --update-ref @~3` from main caused branch ref `b` to move from d86229e to 02fcaf7:
Which is usually not what you want; most of the time you want E', which is E reparented onto B'. But sometimes you want E to remain untouched and stay parented on the original B. Depends on the situation.
I prefer the interactive rebase and use it frequently.
Would much rather “visually” move commits around than accidentally aim “git history” at an orphaned commit hash no longer in my local branch.
It sounds like there was probably an equivalent using an existing command but this is easier for me to understand. Thanks for sharing!
The existing workflow for that would be (there are several possible workflows, but this is what I would do):
Personally, I like it when project's repository represents the history of the project rather than the history of random things developers do on their machines, but you do you.
It's a good rule of thumb to consider shared branches to be append-only, but not every remote branch is "shared" and, as with any proper rule of thumb, you can always find exceptions.
I think that only happens when you work on code as text files (i.e character streams) instead of code (i.e structured content with meaning). Like you have commit A and commit B that is in conflict, you should be glad because that's a rough signal that the intent of A and B differs. Your goal should be to think about how to compose A and B so that both intent survives (unless one supersedes the other). Which means you should be at least familiar with A and B.
The issue I found with people that fears conflict is that they often don't understand either A or B (or both). So they are a bad candidate to actually do the operation. It's not a matter of git's cli interface, it's a matter of codebase comprehension and how well you're familiar with the changes in question.
When you merge a commit in that changed a file that has been already changed since the common ancestor, Git runs a tool of your choice on this file. If the tool fails, it marks the file as needing a merge and doesn't let you commit it until you unmark it to confirm that you have merged it manually. In case of octopus merges, it will just abort early. That's basically its whole behavior when it comes to conflicts.
None of that word salad should matter, but it does. Git will ruin everything with glee and there is always an excuse for why that's fine and it's the user's fault.