Live data from Hacker News

Correct Git commits with git-autofixup

symflower.com

41–50 of 67 posts

Re: Correct Git commits with git-autofixup

#41

Earlier quoted context omitted.

If it grew much bigger I’d do that, but until it’s definitely too large, keeping all of this stuff in ~/.gitconfig is simpler, especially for sharing across heterogeneous machines.

You can add a version-controlled directory to your PATH and put scripts in it. This can be in the same repository as your .gitconfig. So you can graduate aliases to scripts.

Copying a single file is regularly easier, and more flexible when working on machines not set up with your SSH keys or whatever.

Re: Correct Git commits with git-autofixup

#42

Earlier quoted context omitted.

That works. My habit is to make the fix, commit it as "!fixup whatever", start an interactive rebase, move the fixup commit just after the bad commit (M-↑), press f on the fixup commit to tell rebase to merge it with the bad commit, and run the rebase (C-c C-c). This is pretty much the same method as yours, but committing first means the fixup will still be there if you have to cancel & redo the rebase for some reaso…

> move the fixup commit just after the bad commit (M-↑), press f on the fixup commit to tell rebase to merge it with the bad commit, That's what --autosquash is for. If you do fixup commits correctly (using --fixup), it will put them in the correct place and mark them as fixups for you.

> using --fixup

If I understand you correctly, this requires that I think about which commit I want to fixup. Once identified, I can mark my fixup with what commit it should be combined with automatically.

My understanding of the article is that it attempts to automatically figure out which commit to combine with. That’s the feature that I’m interested in.

Re: Correct Git commits with git-autofixup

#43

Earlier quoted context omitted.

Could you share what your workflow would be? I’m assuming you put the point on the line you want to fix, then use Magit to start a rebase at the last commit that changed that line, then apply your changes, then continue? I’m a casual Magit user, so learning from other users would be very beneficial.

I typed it out but HN seems to be rate limiting me or something and tells me I'm "posting too fast". I seem to be able to post shorter comments, though. I've been meaning to write an article on a fixup workflow for a while now. Just need to find somewhere to host it.

You could throw it in a gist to start with.

Re: Correct Git commits with git-autofixup

#44

Earlier quoted context omitted.

That works. My habit is to make the fix, commit it as "!fixup whatever", start an interactive rebase, move the fixup commit just after the bad commit (M-↑), press f on the fixup commit to tell rebase to merge it with the bad commit, and run the rebase (C-c C-c). This is pretty much the same method as yours, but committing first means the fixup will still be there if you have to cancel & redo the rebase for some reaso…

> move the fixup commit just after the bad commit (M-↑), press f on the fixup commit to tell rebase to merge it with the bad commit, That's what --autosquash is for. If you do fixup commits correctly (using --fixup), it will put them in the correct place and mark them as fixups for you.

So I guess what I should be doing is make fix → magit-blame to get the commit ID for the last prior edit → copy commit ID or message to clipboard → magit commit with `c F`, C-s to the commit ID I just copied, and C-c C-c to set up and run the autosquash rebase.

Re: Correct Git commits with git-autofixup

#45
post #37

An excerpt from my ~/.gitconfig, showing a related approach (piggy-backing on git-revise): [alias] # Revise into the commit that last changed File rf = "!f() { if [ $# -eq 0 ]; then REV=\"$(git status --porcelain --untracked-files=no | sed '/^ /d;s/^.. //' | xargs -n1 git rev-list -1 HEAD --)\"; NUM_REVS=\"$(echo \"$REV\" | wc -l)\"; if [ $NUM_REVS -ne 1 ]; then >&2 echo Files in the index were not all last modified…

hg incoming and hg outgoing are really useful. When I am in git, I use this version from https://github.com/sympy/sympy/wiki/Git-hg-rosetta-stone#set... : [alias] outgoing = !git fetch && git log FETCH_HEAD.. incoming = !git fetch && git log ..FETCH_HEAD Feature-wise, the mercurial command is way more powerful: https://www.mercurial-scm.org/doc/hg.1.html#incoming

My aliases for those two deals with remote-tracking branches (see git-rev-parse(1) for documentation of the @{upstream} part if you’re not familiar with it). Might as well provide a more full excerpt:

  # I almost always use glog rather than log.
  glog = log --graph
  # “Short log”
  slog = log --graph --oneline
  # `git id` = `git rev-list --max-count=1` with default refspec HEAD.
  id = "!f() { case \"x$1\" in x-*|x) refspec=HEAD;; *) refspec=\"$1\"; shift;; esac; git rev-list --max-count=1 \"$refspec\" \"$@\"; }; f"
  # `git tip` = `git log --max-count=1` with default refspec HEAD.
  tip = "!f() { case \"x$1\" in x-*|x) refspec=HEAD;; *) refspec=\"$1\"; shift;; esac; git log --max-count=1 \"$refspec\" \"$@\"; }; f"
  # `git out` = glog commits that exist locally but not on the upstream branch. No way to refer to different origins, sorry.
  out = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git glog \"$branch@{upstream}..$branch\" \"$@\"; }; f"
  sout = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git slog \"$branch@{upstream}..$branch\" \"$@\"; }; f"
  # `git in` = glog commits that exist on the upstream branch (remember to fetch them first) but not locally.
  in  = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git glog \"$branch..$branch@{upstream}\" \"$@\"; }; f"
  sin  = "!f() { case \"x$1\" in x-*|x) branch=;; *) branch=\"$1\"; shift;; esac; git slog \"$branch..$branch@{upstream}\" \"$@\"; }; f"

Re: Correct Git commits with git-autofixup

#46

Earlier quoted context omitted.

> move the fixup commit just after the bad commit (M-↑), press f on the fixup commit to tell rebase to merge it with the bad commit, That's what --autosquash is for. If you do fixup commits correctly (using --fixup), it will put them in the correct place and mark them as fixups for you.

So I guess what I should be doing is make fix → magit-blame to get the commit ID for the last prior edit → copy commit ID or message to clipboard → magit commit with `c F`, C-s to the commit ID I just copied, and C-c C-c to set up and run the autosquash rebase.

This process is what I think the article describes and what I’m curious if can be automated by magit itself.

Re: Correct Git commits with git-autofixup

#47
post #4
post #2

git-absorb is another implementation: - https://github.com/tummychow/git-absorb - https://lib.rs/crates/git-absorb

Can anyone give a comparison of the two from experience? I'm painfully familiar with the problem they solve and am delighted to discover they exist. I'd love some input about how they differ.

I have only used `git-absorb`, but one difference from reading the article is that it does its own analysis of your previous commits to choose what each line should `fixup`. Because of this, `git-absorb` can only fix up commits up to a specified base (10 commits earlier by default) when you use it.

Re: Correct Git commits with git-autofixup

#48
post #5

If you're an Emacs user, I must recommend magit ( https://magit.vc/ ) - the interactive rebasing (including squashing/fixups) is one of the best UIs (overall, not just git) I've seen in my life. I'd switch away from Emacs but magit keeps me hooked!

How does Vim's fugitive (https://github.com/tpope/vim-fugitive/) plugin compare to this, in case anyone here has used them both? I've only used it for some basic things so far, and it seems nice enough, but I'm wondering if it's good with more advanced git-fu like the above.

Re: Correct Git commits with git-autofixup

#49

Earlier quoted context omitted.

> move the fixup commit just after the bad commit (M-↑), press f on the fixup commit to tell rebase to merge it with the bad commit, That's what --autosquash is for. If you do fixup commits correctly (using --fixup), it will put them in the correct place and mark them as fixups for you.

> using --fixup If I understand you correctly, this requires that I think about which commit I want to fixup. Once identified, I can mark my fixup with what commit it should be combined with automatically. My understanding of the article is that it attempts to automatically figure out which commit to combine with. That’s the feature that I’m interested in.

Yeah, it does require you to think about it. But magit has really quick and easy diffing and blame so it can make it significantly easier. In practice I rarely have to think very hard before knowing which commit to fixup.
Post reply on HN