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

git delete-merged-branches can delete default branch such as master #1132

Open
bric3 opened this issue Feb 6, 2024 · 10 comments
Open

git delete-merged-branches can delete default branch such as master #1132

bric3 opened this issue Feb 6, 2024 · 10 comments

Comments

@bric3
Copy link
Contributor

bric3 commented Feb 6, 2024

When running git delete-merged-branches on a non default branch, it currently deletes the default branch:

$ git switch -c InlayHintsPassFactory-mayhem
$ git delete-merged-branches
Deleted branch master (was 81901fca2).

It's not a big issue, as it can be recovered by switching to master again, looking at the ref log if needed. But this might be something to fix.

It's possible to get the default branch of the remote named origin

$ git rev-parse --abbrev-ref origin/HEAD
origin/master

If the remote are not named origin this could fail

$ git remote show
bric3
upstream
$ git rev-parse --abbrev-ref origin/HEAD
origin/HEAD
fatal: ambiguous argument 'origin/HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

And not all remote have a default branch

$ git rev-parse --abbrev-ref bric3/HEAD
bric3/HEAD
fatal: ambiguous argument 'bric3/HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
$ ls .git/refs/remotes/bric3/HEAD
".git/refs/remotes/bric3/HEAD": No such file or directory (os error 2)
$ git rev-parse --abbrev-ref upstream/HEAD
upstream/master
$ ls .git/refs/remotes/upstream/HEAD
.git/refs/remotes/upstream/HEAD
@spacewander
Copy link
Collaborator

It seems that it is because the default branch is main? There is a check in the cmd:

branches=$(git branch --no-color --merged | grep -vE "^(\*|\+)" | grep -v "$(git_extra_default_branch)" | grep -v svn)

Either you can configure the default branch to master, or the default branch detection is not correct.

@bric3
Copy link
Contributor Author

bric3 commented Feb 9, 2024

It seems the git_extra_default_branch help function work by looking at configured values or environment variables, if none are present this function falls back to main.

git_extra_default_branch() {
local extras_default_branch init_default_branch
extras_default_branch=$(git config --get git-extras.default-branch)
init_default_branch=$(git config --get init.defaultBranch)
if [ -n "$extras_default_branch" ]; then
echo "$extras_default_branch"
elif [ -n "$init_default_branch" ]; then
echo "$init_default_branch"
else
echo "main"
fi
}

@spacewander
Copy link
Collaborator

So you can configure the default branch to master, if you are using it as the default branch.

@bric3
Copy link
Contributor Author

bric3 commented Feb 11, 2024

Yes but wouldn't that be better if git-extras discover this automatically, using the commands above ?

@spacewander
Copy link
Collaborator

Yes but wouldn't that be better if git-extras discover this automatically, using the commands above ?

Would you happen to have any suggestions? The git_extra_default_branch is just reading the configured value.

@bric3
Copy link
Contributor Author

bric3 commented Feb 15, 2024

@spacewander Sorry for the late reply. Yes I think what I proposed in the top message could help resolve the default branch :

git rev-parse --abbrev-ref ${the_remote}/HEAD

@spacewander
Copy link
Collaborator

@spacewander Sorry for the late reply. Yes I think what I proposed in the top message could help resolve the default branch :

git rev-parse --abbrev-ref ${the_remote}/HEAD

Err... But there may be multiple remotes.

@bric3
Copy link
Contributor Author

bric3 commented Feb 16, 2024

Indeed, I suggest the following approach

  1. If there's a single remote use it
  2. If multiple, only look up origin, then maybe upstream.
  3. If not possible look at the existing init default branch

@spacewander
Copy link
Collaborator

Indeed, I suggest the following approach

  1. If there's a single remote use it
  2. If multiple, only look up origin, then maybe upstream.
  3. If not possible look at the existing init default branch

It seems too complex to me, which may introduce strange behavior. For example, the git-extras in my local machine has two remotes:

origin	[email protected]:spacewander/git-extras (fetch)
origin	[email protected]:spacewander/git-extras (push)
own	[email protected]:tj/git-extras (fetch)
own	[email protected]:tj/git-extras (push)

The origin(https://github.com/spacewander/git-extras) 's default branch is master, while the own(https://github.com/tj/git-extras) 's default branch is main.

The guess can't guarantee it's 100% correct.

@hyperupcall @vanpipy
What about your opinion?

@hyperupcall
Copy link
Collaborator

hyperupcall commented Feb 18, 2024

@spacewander I think it would be simple and effective to skip the deletion of branches with hardcoded values of master, main, trunk, default, development, stable, release, and production. I think that should detect 99% of cases, and will ignore some useful branches that may not be the default branch of any remote. To prevent confusion over the change of behavior, I think a warning should be emitted if we ignore a branch.

We can also read the config value for the default init branch and add that.

Indeed, I suggest the following approach

If there's a single remote use it
If multiple, only look up origin, then maybe upstream.
If not possible look at the existing init default branch

I agree with @spacewander, although it is a good heuristic, I think there is too much uncertainty around it and it will invariably do different things, even on the same computer. I for one, always use me instead of origin.

Another idea is to loop over all remotes, and add any of their default branches to the ignore list. I am not completely certain that it will not introduce many false positives.

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

No branches or pull requests

3 participants