git-town / git-town

Git branches made easy
https://www.git-town.com
MIT License
2.66k stars 108 forks source link

Why does `git town` do `git push -u origin master` on`git town sync` #3241

Closed breml closed 8 months ago

breml commented 8 months ago

Situation

I am on a feature branch (child) forked form master some time back. When I come back to this feature branch, I run git town sync to get it up-to-date with the recent changes on master.

According to the output of git town, the following commands are executed:

git fetch --prune --tags
git checkout master
git push -u origin master

The last command fails, since in our case the master branch is protected and all changes need to go through PR.

After the git checkout master command, I see the message:

Your branch is behind 'origin/master' by 9 commits, and can be fast-forwarded.

Question

I do not expect git town to try to update master at this stage. Why is git town trying to push to master at this stage? If the local master can be updated by just fast-forward, I would expect git town to actually do exactly this.

breml commented 8 months ago

Additional context:

$ git town config

Branches:
  main branch: master
  perennial branches: master, testing, live
...
kevgo commented 8 months ago

Hi @breml, can you please post the full output of git town sync --verbose? Anonymize personal information in it if needed. Thanks!

breml commented 8 months ago

Hi @kevgo, I moved on with the branch in question. As soon as I have an other example, I will share it here.

kevgo commented 8 months ago

Thanks! Another observation: You are listing master as both your main branch and a perennial branch. That's redundant, the main branch is automatically considered a perennial branch. You can remove master from the perennial branches.

breml commented 8 months ago

I added master to the perennial branch list when I first observed the issues with git worktree since I got insecure if it is my fault with the config. But I will remove this again.

breml commented 8 months ago

I have the same situation again and I executed git town sync --verbose. The output is really verbose and I don't feel comfortable to share this information, since it is work related. Can you give me some pointers on what to look out for?

kevgo commented 8 months ago

The goal of Git Town is to be fully intuitive. If you are unsure about something, and git-town.com doesn't answer your question, that's either a functional or a documentation bug.

kevgo commented 8 months ago

I have the same situation again and I executed git town sync --verbose. The output is really verbose and I don't feel comfortable to share this information, since it is work related. Can you give me some pointers on what to look out for?

Can you replace feature branch names with branch-1, branch-2, etc? If not, I'm mostly looking for the output around the master branch. I want to understand why Git Town runs git push -u origin master on your machine when master already has a tracking branch.

kevgo commented 8 months ago

Alternatively, if you could post the output of git branch -vva and replace the branch names there, that would also be helpful.

breml commented 8 months ago

OK, I can share it like this:

Output of git branch -vva is 262 lines long (it is what it is, a mono repo with a lot of history) and can be split in 4 categories:

  1. 214 lines starting with remotes/origin/... with some branch name, commit id and the first line of the description of the commit
  2. 46 lines starting with local-branch-name (not being remotes), so these are local branches, again with commit id and first line of description of the commit
  3. 1 line starting with * master looking like this * master 02c192178 [origin/master: behind 2] some commit description...
  4. 1 line starting with + other-branch-name looking like this + other-branch-name 938340299 (/some/directory/worktrees/branch-name) [origin/branch-name] some commit description

The 4th item is a git worktree (currently I only have one, I reduced the number of worktrees after the issues I was facing earlier this week, #3230 ).

I hope this helps.

breml commented 8 months ago

Before the git push -u origin master I see the following output:

git branch -vva with the output described above

and then

(verbose) git rev-parse --verify --abbrev-ref @{-1}
master

[branch-name] git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

branch-name above is the branch I started the git town sync --verbose from.

kevgo commented 8 months ago

Looks like your feature branch (called branch-name here) was in another worktree than master. I have reproduced your scenario in #3248 and it works for me. So I don't really get closer to solving this mystery.

Can you share the output of git town config?

breml commented 8 months ago

Sorry, I was not accurate about the branch names. I updated my above messages (in particular the name of the branch in the "linked worktree").

I started the git town sync from the "main worktree". The branch, which is checked out in the git worktree (mentioned above) is a branch not related to the rebase (sync) I wanted to perform.

Again, sorry for the confusion.

breml commented 8 months ago

My git town config looks like this:

$ git town config

Branches:
  main branch: master
  perennial branches: live, testing
  perennial regex: (not set)
  parked branches: (none)
  contribution branches: (none)
  observed branches: some-branch

Configuration:
  offline: no
  run pre-push hook: yes
  push new branches: no
  ship deletes the tracking branch: no
  sync-feature strategy: rebase
  sync-perennial strategy: rebase
  sync with upstream: no
  sync before shipping: no

Hosting:
  hosting platform override: github
  GitHub token: <redacted>
  GitLab token: (not set)
  Gitea token: (not set)

Branch Lineage:
  master
    branch-name-3
    branch-name-2
    branch-name
    branch-name-1
$ git town --version
Git Town 13.0.1
kevgo commented 8 months ago

The output you shared does not execute git push -u origin master. It's really hard to debug a problem with such little information. It would be super helpful if you post the entire output of a git sync --verbose command that reproduces the issue, with branches unrelated to the problem removed.

If you are concerned about publishing on this public website, maybe you can send me the output privately to kevin.goslar@gmail.com. I'll use it only to debug this issue and then delete the email.

I have added additional end-to-end tests in https://github.com/git-town/git-town/pull/3250 that reproduce possible causes for this issue. However, I still cannot reproduce this issue.

breml commented 8 months ago

I will try to provide more details. Just something I observed now:

After the last command (git town sync --verbose) failed at the stage, where git town wanted to push to master, I now tried to run an other git town sync --verbose. Since the previous command has not finished properly, git town offers me 5 options to choose from:

unfinished Git Town command

You have an unfinished "sync" command
that ended on the "master" branch
5 hours ago. Please choose how to proceed.

0 > Quit without running anything
1   Continue the "sync" command after having resolved conflicts
2   Skip the current branch and continue the "sync" command on the next branch
3   Undo the previous "sync" command
4   Discard the unfinished state and run the new command

If I select # 3, then git town wants to do the following command: git push origin :master. If I read this correctly, it would basically try to delete the master branch on origin. I am really glad, that the prompt to enter my password for the ssh key does prevent the commands from being executed.

breml commented 8 months ago

I did an other test. This time I cloned the repo to a new directory. In this new clone, there is no git worktree, so we can rule this out. After cloning the repo, I artificially set my local master branch two commits back (by executing git reset --hard HEAD^1 twice). I have setup git town with the same settings that I have in the other clone (shared below again), with one change, instead of selecting live and testing as perennial branches (they have not been offered to me, since I don't have them as local branches, only as remote), I added a regex, which should match the two branches. I then checked out the branch, that I want to sync on master. I set the parent branch to master (with git town set-parent) I then ran git town sync --verbose and I get the following (redacted) output:

$ git town sync --verbose

(verbose) git version
git version 2.34.1

(verbose) git config -lz --global
<redacted>
(verbose) git config -lz --local
<redacted>

(verbose) git rev-parse --show-toplevel
/tmp/repo

(verbose) git stash list

(verbose) git status --long --ignore-submodules
On branch foobar
Your branch is up to date with 'origin/foobar'.

nothing to commit, working tree clean

(verbose) git branch -vva
<lots of branches redacted>
* foobar                         fd43cbb83 [origin/foobar] comment
  remotes/origin/foobar          fd43cbb83 comment
  remotes/origin/testing         db39f0255 comment
  remotes/origin/HEAD            -> origin/master
  remotes/origin/master          41c3f1280 comment
  master                         02c192178 [origin/master: behind 2] comment
  remotes/origin/live            cd7d1d1ea comment

(verbose) git remote
origin

[foobar] git fetch --prune --tags
Enter passphrase for key '.../id_ed25519_sk':

(verbose) git branch -vva
<lots of branches redacted>
* foobar                         fd43cbb83 [origin/foobar] comment
  remotes/origin/foobar          fd43cbb83 comment
  remotes/origin/testing         db39f0255 comment
  remotes/origin/HEAD            -> origin/master
  remotes/origin/master          41c3f1280 comment
  master                         02c192178 [origin/master: behind 2] comment
  remotes/origin/live            cd7d1d1ea comment

(verbose) git rev-parse --verify --abbrev-ref @{-1}
master

[foobar] git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

[master] git push -u origin master
Enter passphrase for key '.../id_ed25519_sk':
To github.com:corp/repo.git
 ! [rejected]            master -> master (non-fast-forward)
error: failed to push some refs to 'github.com:corp/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

(verbose) git branch -vva
<lots of branches redacted>
  foobar                         fd43cbb83 [origin/foobar] comment
  remotes/origin/foobar          fd43cbb83 comment
  remotes/origin/testing         db39f0255 comment
  remotes/origin/HEAD            -> origin/master
  remotes/origin/master          41c3f1280 comment
* master                         02c192178 [origin/master: behind 2] comment
  remotes/origin/live            cd7d1d1ea comment

(verbose) git config -lz --global
<redacted>
(verbose) git config -lz --local
<redacted>

(verbose) git stash list

(verbose) git status --long --ignore-submodules
On branch master
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean

Ran 18 shell commands.
Error: exit status 1

To continue after having resolved conflicts, run "git town continue".
To go back to where you started, run "git town undo".
To continue by skipping the current branch, run "git town skip".

Output of git town config (redacted):

$ git town config

Branches:
  main branch: master
  perennial branches: (none)
  perennial regex: ^(live|testing)$
  parked branches: (none)
  contribution branches: (none)
  observed branches: (none)

Configuration:
  offline: no
  run pre-push hook: yes
  push new branches: no
  ship deletes the tracking branch: no
  sync-feature strategy: rebase
  sync-perennial strategy: rebase
  sync with upstream: no
  sync before shipping: no

Hosting:
  hosting platform override: github
  GitHub token: <redacted>
  GitLab token: (not set)
  Gitea token: (not set)

Branch Lineage:
  master
    foobar

I hope this information helps. If not, the next place to look would be the global and the local config I guess.

breml commented 8 months ago

I checked my global and local config and I think I can share the following (again somewhat redacted):

For the global settings, I removed everything regarding user, merge.tool, diff.tool, pager, core.editor, core.excludefile, color, alias, includeif.gitdir and url.ssh

$ git config -l --global
rerere.enabled=true
rerere.autoupdate=true
absorb.maxstack=10
absorb.onefixuppercommit=true
absorb.autostageifnothingstaged=true
push.default=simple
branch.autosetuprebase=never
branch.sort=-committerdate
init.defaultbranch=master
$ git config -l --local
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=git@github.com:corp/repo.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
branch.foobar.remote=origin
branch.foobar.merge=refs/heads/foobar
git-town.github-token=<redacted>
git-town.hosting-platform=github
git-town.main-branch=master
git-town.perennial-branches=
git-town.perennial-regex=^(live|testing)$
git-town.ship-delete-tracking-branch=false
git-town.sync-feature-strategy=rebase
git-town.sync-upstream=false
git-town-branch.foobar.parent=master
kevgo commented 8 months ago

If I select # 3, then git town wants to do the following command: git push origin :master. If I read this correctly, it would basically try to delete the master branch on origin. I am really glad, that the prompt to enter my password for the ssh key does prevent the commands from being executed.

Thanks for reporting this. Yes, that would delete the master branch on origin, which is pretty bad. Trying to reproduce this problem, I have added end-to-end tests that cover this scenario in https://github.com/git-town/git-town/pull/3254. However, none of these tests reproduce the behavior you describe.

Did you run both git sync --verbose commands in the same worktree? Can you please post the full output of a git sync --verbose command that exhibits this behavior?

breml commented 8 months ago

So my separate clone is still in this error state so I executed git town sync --verbose again and then selected option 3:

$ git town sync --verbose

(verbose) git version
git version 2.34.1

(verbose) git config -lz --global
<redacted>
(verbose) git config -lz --local
<redacted>
(verbose) git rev-parse --show-toplevel
/tmp/repo

(verbose) git stash list

(verbose) git status --long --ignore-submodules
On branch foobar
Your branch is up to date with 'origin/foobar'.

nothing to commit, working tree clean

(verbose) git branch -vva
<lots of branches redacted>
* foobar                                fd43cbb83 [origin/foobar] comment
  remotes/origin/foobar                 fd43cbb83 comment
  remotes/origin/testing                db39f0255 comment
  remotes/origin/HEAD                   -> origin/master
  remotes/origin/master                 41c3f1280 comment
  master                                02c192178 [origin/master: behind 2] comment
  remotes/origin/live                   cd7d1d1ea comment

unfinished Git Town command

You have an unfinished "sync" command
that ended on the "master" branch
7 hours ago. Please choose how to proceed.

0   Quit without running anything
1   Continue the "sync" command after having resolved conflicts
2   Skip the current branch and continue the "sync" command on the next branch
3 > Undo the previous "sync" command
4   Discard the unfinished state and run the new command

Handle unfinished command: undo

[foobar] git push origin :master
Enter passphrase for key '.../id_ed25519_sk':
kevgo commented 8 months ago

@breml Thank so much for sending these detailed logs! 🙏 Thanks to them I am getting closer to understanding what is going on here. I think the culprit is that on your machine git branch -vva lists local branches in an unexpected order, specifically local branches mixed with remote branches.

Here is an example. When running git branch -vva on your machine, it lists the remote branch first, then the local branch. I'm omitting all other branches for brevity.

  remotes/origin/master          41c3f1280 comment
  master                         02c192178 [origin/master: behind 2] comment

The same query on my machine (and on Git Town CI servers) lists the local branch first, then the remote branch.

  main                         43920d28 [origin/main] Use git reflog instead of git log --reflog (#3262)
  remotes/origin/main          43920d28 Use git reflog instead of git log --reflog (#3262)

Git Town currently assumes that local branches are always listed before their tracking branches. Receiving them in another order makes Git Town wrongfully assume that master and origin/master are two different branches. This explains all the weird behavior you observe, like trying to create a new tracking branch for master and trying to delete the remote master branch.

Apparently there are a number of options to configure branch sorting, like branch.sort and --sort=<key>. I wasn't aware of them. I'm glad you caught this without getting your remote master branch pulverized (and you in trouble for it) and took the time to report it!

kevgo commented 8 months ago

From https://git-scm.com/docs/git-branch#Documentation/git-branch.txt---sortltkeygt (highlights by me):

Sort order defaults to the value configured for the branch.sort variable if it exists, or to sorting based on the full refname (including refs/... prefix). This lists detached HEAD (if present) first, then local branches and finally remote-tracking branches.

kevgo commented 8 months ago

Your configuration contains a custom branch.sort setting. From https://github.com/git-town/git-town/issues/3241#issuecomment-2026189233 (highlights by me):

$ git config -l --global rerere.enabled=true rerere.autoupdate=true absorb.maxstack=10 absorb.onefixuppercommit=true absorb.autostageifnothingstaged=true push.default=simple branch.autosetuprebase=never branch.sort=-committerdate init.defaultbranch=master

kevgo commented 8 months ago

I will update Git Town to parse branches independent of ordering and make a bug fix release. As a temporary workaround until this is released, you could remove the branch.sort from your Git config for the time being.

kevgo commented 8 months ago

Simpler bug fix: run git branch -vva --sort=refname, then it will ignore the configuration in branch.sort and always sort in the default way.

kevgo commented 8 months ago

@breml I have released v13.0.2 that should fix the issue you describe in this ticket. I'm really curious if this resolves the issues for you.

Thanks again for finding and reporting so many issues, and your patience and detailed bug reports. You have helped make Git Town significantly more robust for everybody. With 13.0.2 you should be able to use Git Town productively now, including workspaces. I know this sounds like a big promise given how many issues you have experienced so far. But progress comes from pushing the boundaries and hard work to make the impossible possible. Please keep pushing and reaching out if you encounter any other irregularities. We really appreciate your help making Git Town even more useful to more people!

breml commented 8 months ago

@kevgo thanks for the fix. I will give it a try next week.

breml commented 8 months ago

@kevgo I updated to latest version (13.0.2) and I executed git town sync --verbose on my broken repository (mentioned above) and git town still tires to delete my master branch with git push origin :master if I select option # 3 (Undo the previous "sync" command).

I wonder, if there should be a safety guard to never try to delete main or perennial branches.

breml commented 8 months ago

I used git town (version 13.0.2) for my normal work today and I have not observed any wrong behavior so far, so it looks like 13.0.2 does resolve this issue.

kevgo commented 8 months ago

Really great to hear! 👍