Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pathspecs in --cut #134

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

krobelus
Copy link
Contributor

Sometimes I want to extract a small number of changes from a commit
that touches loads of files. Since the cut mode prompts about every
single file, there is no convenient way to do this.

Teach --cut about pathspec arguments. This allows to use

git revise --cut my-commit -- path/to/my/file
a

to extract to a separate commit all changes in the given file.

cc @Munsio

@krobelus krobelus changed the base branch from master to main May 22, 2023 20:20
Comment on lines 277 to 285
index.git("reset", "--patch", final_tree.persist().hex(), "--", ".", stdout=None)
index.git(
"reset",
"--patch",
final_tree.persist().hex(),
"--",
*pathspecs if pathspecs else ".",
stdout=None,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work from a subdirectory (when pathspecs (or ".") are relative to the current directory)?

I'm actually using this daily, and happened to try it from a subdirectory now. It works if I use a repo-absolute path from within the subdirectory. But looking at the code, I'm surprised that that "." doesn't otherwise mean the subdirectory (not that I think it should).

Idea: You could make the tests run from a subdirectory to cover this aspect too.

Copy link
Contributor

@anordal anordal Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an alternative to git reset?

This appears to be a quirk of git reset: Its pathspec arguments are not relative. Although (according to gitglossary(7)) it is command defined whether they are relative, I think relative is the only sensible interpretation: It is what your shell completes, whereas a toplevel relative pathspec is denoted by for example a :/ prefix. So if we want that, we would need to not use git reset, or work around it. It also explains how the dot becomes the toplevel directory.

Fixing it the obvious way (by prefixing the current directory) would necessitate parsing the pathspec, which looks a bit undesirable to have to deal with: Not just parsing wise (even parsing the short form of the magic character prefix requires knowing the full set of magic characters), but we need to understand it, to know whether the path is supposed to be toplevel relative or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to be a quirk of git reset: Its pathspec arguments are not relative

No. According to my testing they are treated like any other pathspec (relative unless prefixed with :/ or /).

If I run

mkdir a b
touch a/1 b/2
git add a b
cd a
git reset --patch -- 1

that works as expected (only includes a/1, not b/2).

Now if I cancel the last command and do

git reset --patch -- .

it will prompt to reset anything inside a/, so effectively the same.

It works if I use a repo-absolute path from within the subdirectory.

This is surprising.
Also, relative paths don't work (they should).

This is a bug in git-revise.
By default it runs git reset with the Git worktree as working directory.

        if cwd is None:
            cwd = getattr(self, "workdir", None)

Because of this, our -- . doesn't make a difference today (it is confusing though).
Once we fix this however, it will cause deviant behavior from git reset.
I think we should remove it.
I'm not sure why it was added in 74c59ad (Improve performance and UX for --cut, 2019-07-21), perhaps by accident.

Copy link
Contributor

@anordal anordal Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. You found the right problem.

I had a go at running git from cwd (which indeed makes the pathspecs work from a subdirectory):
https://github.com/anordal/git-revise/commits/run-git-from-cwd

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted for a minimal fix here but I agree that it might be worth to change the default to keep the working directory, instead of using the work tree root.
However we need to be careful, your patch changes the behavior of our call to git ls-files. Not sure if for better or worse.

gitrevise/tui.py Outdated
@@ -36,6 +36,9 @@ def build_parser() -> ArgumentParser:
nargs="?",
help="target commit to apply fixups to",
)
parser.add_argument(
"pathspecs", nargs="*", help="make --cut select only from matching files"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably should set it up to only be allowed when --cut is used? I think clap supports this kind of thing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that was a regression, fixed

Sometimes I want to extract a small number of changes from a commit
that touches loads of files. Since the cut mode prompts about every
single file, there is no convenient way to do this.

Teach --cut about pathspec arguments.  This allows to use

	git revise --cut my-commit -- path/to/my/file
	a

to extract to a separate commit all changes in the given file.

In future we could support pathspecs in other subcommands.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants