git-extras icon indicating copy to clipboard operation
git-extras copied to clipboard

`git delete-merged-branches` can delete default branch such as `master`

Open bric3 opened this issue 1 year ago • 10 comments

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

bric3 avatar Feb 06 '24 10:02 bric3

It seems that it is because the default branch is main? There is a check in the cmd: https://github.com/tj/git-extras/blob/5f19424a50fda7a81f64955e96c575445577c3ea/bin/git-delete-merged-branches#L3

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

spacewander avatar Feb 09 '24 03:02 spacewander

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.

https://github.com/tj/git-extras/blob/5f19424a50fda7a81f64955e96c575445577c3ea/helper/git-extra-utility#L8-L19

bric3 avatar Feb 09 '24 17:02 bric3

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

spacewander avatar Feb 11 '24 13:02 spacewander

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

bric3 avatar Feb 11 '24 17:02 bric3

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.

spacewander avatar Feb 12 '24 02:02 spacewander

@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

bric3 avatar Feb 15 '24 10:02 bric3

@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.

spacewander avatar Feb 16 '24 04:02 spacewander

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

bric3 avatar Feb 16 '24 08:02 bric3

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?

spacewander avatar Feb 17 '24 06:02 spacewander

@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.

hyperupcall avatar Feb 18 '24 08:02 hyperupcall