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

Add support for determining default branch when calling hub pull-request form worktree #2485

Closed
wants to merge 2 commits into from
Closed

Add support for determining default branch when calling hub pull-request form worktree #2485

wants to merge 2 commits into from

Conversation

csaska
Copy link

@csaska csaska commented Feb 28, 2020

Fixes #2484 .

When hub pull-request is called from a worktree, hub does not correctly find the default branch for the repo.

This code is a bit of a hack; it attempts to check for worktree in the path pointed to by $GIT_DIR/.git of the worktree.

This should work for the default cause; however, I am not sure if it will work in all scenarios, specifically when users decide to set git config extensions.worktreeConfig true

@csaska
Copy link
Author

csaska commented Feb 28, 2020

On second thought, perhaps these changes should be added to this function
https://github.com/github/hub/blob/b0db79dbf3988dd25c0053abc39a77fc92c46bfc/git/git.go#L26

@csaska
Copy link
Author

csaska commented Feb 28, 2020

Perhaps the fix is as simple as changing --git-dir to --git-common-diras long as the ref being used is a shared ref i.e. under the .git/ref dir

https://github.com/github/hub/blob/b0db79dbf3988dd25c0053abc39a77fc92c46bfc/git/git.go#L31

Copy link
Owner

@mislav mislav left a comment

Choose a reason for hiding this comment

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

Thank you! I wonder if this is safe to apply across the board, or whether it might have unwanted consequences 🤔

git/git.go Outdated
@@ -28,7 +28,7 @@ func Dir() (string, error) {
return cachedDir, nil
}

dirCmd := gitCmd("rev-parse", "-q", "--git-dir")
dirCmd := gitCmd("rev-parse", "-q", "--git-common-dir")
Copy link
Owner

Choose a reason for hiding this comment

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

What is the earliest git version where --git-common-dir was introduced?

Copy link
Author

Choose a reason for hiding this comment

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

Looks like it was first introduced in https://git-scm.com/docs/git-rev-parse/2.5.1.

Copy link
Author

Choose a reason for hiding this comment

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

Based on these two pages, I'm inclined to say that it will always work, even if the path is relative.

https://git-scm.com/docs/git

GIT_COMMON_DIR

If this variable is set to a path, non-worktree files that are normally in $GIT_DIR will be taken from this path instead. Worktree-specific files such as HEAD or index are taken from $GIT_DIR

commondir

If this file exists, $GIT_COMMON_DIR (see git[1]) will be set to the path specified in this file if it is not explicitly set. If the specified path is relative, it is relative to $GIT_DIR. The repository with commondir is incomplete without the repository pointed by "commondir"

Copy link
Author

Choose a reason for hiding this comment

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

If you're setting GIT_COMMON_DIR, then based on the docs, it seems like you should be expecting this dir to be used for all non-worktree files. I guess your question though is concerned with what other code is using Dir()? So, what other hub features rely on GIT_DIR, and do they ever expect to use worktree-specific files?

Copy link
Owner

Choose a reason for hiding this comment

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

Requiring git 2.5 all of the sudden is a dealbreaker, since thus far we've supported git 1.7+

Copy link
Author

@csaska csaska Feb 28, 2020

Choose a reason for hiding this comment

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

Are you against something like?

dirCmd := gitCmd("rev-parse", "-q", "--git-dir")
parseCmd.Stderr = nil
gitDir, err := parseCmd.Output()

parseCmd := gitCmd("rev-parse", "--is-inside-worktree")
parseCmd.Stderr = nil
isWorktree, err := parseCmd.Output()

if (isWorkTree) {
     // try and use GIT_DIR/../../
     gitDir = gitDir + "/../../"

     // check if path exists, otherwise fallback to regular behavior
}

edit:

actually, I don't think it's a problem that this option isn't in earlier versions of git. I think git rev-parse fails silently if an option doesn't exist. So we could check if git rev-parse --git-common-dir returns a valid path, otherwise fallback

Alternatively, we could do git rev-parse --local-env-vars, see if GIT_COMMON_DIR exists and use it if it does, otherwise fallback

I will work on both and test them on git 1.7+. Stay tuned.

Copy link
Author

@csaska csaska Feb 28, 2020

Choose a reason for hiding this comment

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

Okay, so git worktrees aren't supported in [email protected]. Therefore, any git command attempted from a worktree in [email protected] will fail.

So, changing this code to use git rev-parse --git-common-dir instead of git rev-parse --git-dir will not change the behavior in any git release that does not include worktree support.

FE37C11A-1C99-4254-AE09-AC310B7794CF_4_5005_c

13DF821F-EF1A-412C-809C-8CA49AA1DCA2_1_201_a

6F27B81F-3E8F-4CBC-8392-22602FC5006E_1_201_a

worktrees were introduced in [email protected].

Copy link
Author

@csaska csaska Feb 28, 2020

Choose a reason for hiding this comment

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

Okay so now looking at the first release of git with worktrees.

4E8EC289-0833-4D7D-81A2-FEA4AE288F74_1_201_a

Based on these results, I would say there is no issue in changing git rev-parse --git-dir to git rev-parse --git-common-dir. If you are in a worktree prior to [email protected], your rev-parse command will fail anyway.

@mislav do you have any other concerns?

Copy link
Owner

@mislav mislav Feb 29, 2020

Choose a reason for hiding this comment

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

Based on these results, I would say there is no issue in changing git rev-parse --git-dir to git rev-parse --git-common-dir. If you are in a worktree prior to [email protected], your rev-parse command will fail anyway.

That's a good point; thank you for looking into this in such depth!

I'm wondering what about when you're not in a worktree, but in a regular git working directory, and you issue git rev-parse --git-common-dir with an old git version. Wouldn't it fail because --git-common-dir flag is not recognized there? If so, should we perhaps run git rev-parse --git-dir as fallback?

Copy link
Author

Choose a reason for hiding this comment

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

lol yes you're right...I got so hung up on worktrees that I forgot about the nomal scenario.

Comment on lines +30 to +39
gitDir, err := CommondirName()
if err != nil {
return "", fmt.Errorf("Not a git repository (or any of the parent directories): .git")
// Fall back for older version of git prior to v2.7.0 (added worktrees)
dirCmd := gitCmd("rev-parse", "--git-dir")
dirCmd.Stderr = nil
output, err := dirCmd.Output()
if err != nil {
return "", fmt.Errorf("Not a git repository (or any of the parent directories): .git")
}
gitDir = firstLine(output)
Copy link
Author

@csaska csaska Feb 29, 2020

Choose a reason for hiding this comment

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

@mislav Thanks for the responses! I added this function. Thought being that this perhaps isn't the last time a hub command has different behavior in a worktree.

https://github.com/github/hub/blob/479ed29d9253c88f4da78caf8c9061a6da760528/git/git.go#L82

In Dir(), if the function returns an error, we fall back to the original behavior of the code

Copy link
Owner

@mislav mislav left a comment

Choose a reason for hiding this comment

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

I finally looked into this in depth and realized that the main problem is that we're trying to figure out the correct .git directory to manually read the .git/refs/remotes/<remote>/HEAD file from. This PR just feels like we're making an already complicated approach even more complicated.

What if we just use git commands to read the branch instead? Then we don't have to implement any manual reading of files under the .git directory, and we can have git resolve everything correctly in worktrees.

I've opened this exploration in #2489, let me know what you think

@csaska
Copy link
Author

csaska commented Mar 1, 2020

This PR just feels like we're making an already complicated approach even more complicated.

I completely agree.

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.

Hub doesn't use my default base branch when executing pull-request cmd from worktrees
2 participants