mbox series

[00/28] Use main as default branch name

Message ID pull.762.git.1605221038.gitgitgadget@gmail.com (mailing list archive)
Headers show
Series Use main as default branch name | expand

Message

Philippe Blain via GitGitGadget Nov. 12, 2020, 10:43 p.m. UTC
This is the big one. This changes the default of init.defaultBranch to main,
reflecting what many open source projects already did (which was followed by
GitHub, Azure Repos and others).

Instead of one huge patch that reflects essentially a search-and-replace in
the test suite, this patch series splits the changes up into chunks that are
intended to be smaller than 100kB so that they are not rejected by the Git
mailing list. Interspersed between those changes are adjustments e.g. in
alignment, to make it easier to review (or recreate) the search-and-replace
patches.

Note that this branch is based on next, mostly because it would otherwise
conflict with en/merge-tests, jk/diff-release-filespec-fix and 
ds/maintenance-part-3.

The semantic conflict with pk/subsub-fetch-fix consists of just a single
line in t/t5526-fetch-submodules.sh needing s/master/main/g.

To avoid even more conflicts with topics that did not even make it to seen 
yet, this patch series specifically excludes t3404, t4013, t5310, t6300,
t7064, t7817, t9902: in those test scripts, we will still use master for the
time being. Once the topics in question have settled, I will send the
appropriate follow-up patches to adjust them to use main instead.

Don Goodman-Wilson (1):
  Change the default branch name to `main`

Johannes Schindelin (27):
  t0060: preemptively adjust alignment
  t[01]*: adjust the references to the default branch name "main"
  t2*: adjust the references to the default branch name "main"
  t3[0-3]*: adjust the references to the default branch name "main"
  t3416: preemptively adjust alignment in a comment
  t34*: adjust the references to the default branch name "main"
  t3[5-9]*: adjust the references to the default branch name "main"
  t4*: adjust the references to the default branch name "main"
  t5323: prepare centered comment for `master` -> `main`
  t5[0-4]*: adjust the references to the default branch name "main"
  t5503: prepare aligned comment for replacing `master` with `main`
  t550*: adjust the references to the default branch name "main"
  t551*: adjust the references to the default branch name "main"
  t55[23]*: adjust the references to the default branch name "main"
  t55[4-9]*: adjust the references to the default branch name "main"
  t5[6-9]*: adjust the references to the default branch name "main"
  t6[0-3]*: adjust the references to the default branch name "main"
  t64*: preemptively adjust alignment to prepare for `master` -> `main`
  t6[4-9]*: adjust the references to the default branch name "main"
  t7[0-4]*: adjust the references to the default branch name "main"
  t7[5-9]*: adjust the references to the default branch name "main"
  t8*: adjust the references to the default branch name "main"
  t9[0-4]*: adjust the references to the default branch name "main"
  t9[5-7]*: adjust the references to the default branch name "main"
  tests(git-p4): transition to the default branch name `main`
  t99*: adjust the references to the default branch name "main"
  tests: drop prereq `PREPARE_FOR_MAIN_BRANCH` where no longer needed

 refs.c                                        |   2 +-
 t/annotate-tests.sh                           |   8 +-
 t/lib-cvs.sh                                  |   2 +-
 t/lib-submodule-update.sh                     |   2 +-
 t/t0002-gitfile.sh                            |   6 +-
 t/t0020-crlf.sh                               |   8 +-
 t/t0021-conversion.sh                         |  40 +-
 t/t0027-auto-crlf.sh                          |   4 +-
 t/t0028-working-tree-encoding.sh              |   4 +-
 t/t0041-usage.sh                              |  10 +-
 t/t0050-filesystem.sh                         |   6 +-
 t/t0060-path-utils.sh                         |   4 +-
 t/t0100-previous.sh                           |  18 +-
 t/t1004-read-tree-m-u-wf.sh                   |  40 +-
 t/t1008-read-tree-overlay.sh                  |   2 +-
 t/t1009-read-tree-new-index.sh                |   4 +-
 t/t1011-read-tree-sparse-checkout.sh          |   2 +-
 t/t1021-rerere-in-workdir.sh                  |   2 +-
 t/t1090-sparse-checkout-scope.sh              |  10 +-
 t/t1091-sparse-checkout-builtin.sh            |   2 +-
 t/t1300-config.sh                             |   8 +-
 t/t1301-shared-repo.sh                        |   4 +-
 t/t1305-config-include.sh                     |   2 +-
 t/t1309-early-config.sh                       |   4 +-
 t/t1400-update-ref.sh                         |  72 +--
 t/t1402-check-ref-format.sh                   |  28 +-
 t/t1403-show-ref.sh                           |  18 +-
 t/t1405-main-ref-store.sh                     |  42 +-
 t/t1406-submodule-ref-store.sh                |  30 +-
 t/t1407-worktree-ref-store.sh                 |  32 +-
 t/t1408-packed-refs.sh                        |  12 +-
 t/t1410-reflog.sh                             |  56 +-
 t/t1411-reflog-show.sh                        |   2 +-
 t/t1413-reflog-detach.sh                      |  24 +-
 t/t1414-reflog-walk.sh                        |  12 +-
 t/t1416-ref-transaction-hooks.sh              |  10 +-
 t/t1430-bad-ref-name.sh                       |  52 +-
 t/t1450-fsck.sh                               |   2 +-
 t/t1500-rev-parse.sh                          |   4 +-
 t/t1503-rev-parse-verify.sh                   |  28 +-
 t/t1505-rev-parse-last.sh                     |   8 +-
 t/t1506-rev-parse-diagnosis.sh                |   4 +-
 t/t1507-rev-parse-upstream.sh                 |  40 +-
 t/t1508-at-combinations.sh                    |  10 +-
 t/t1511-rev-parse-caret.sh                    |  26 +-
 t/t1512-rev-parse-disambiguation.sh           |   2 +-
 t/t1513-rev-parse-prefix.sh                   |   4 +-
 t/t1514-rev-parse-push.sh                     |  16 +-
 t/t1700-split-index.sh                        |   2 +-
 t/t2007-checkout-symlink.sh                   |  10 +-
 t/t2009-checkout-statinfo.sh                  |   8 +-
 t/t2010-checkout-ambiguous.sh                 |   4 +-
 t/t2011-checkout-invalid-head.sh              |  16 +-
 t/t2012-checkout-last.sh                      |  48 +-
 t/t2015-checkout-unborn.sh                    |   2 +-
 t/t2017-checkout-orphan.sh                    |  44 +-
 t/t2020-checkout-detach.sh                    |  28 +-
 t/t2022-checkout-paths.sh                     |  22 +-
 t/t2023-checkout-m.sh                         |  10 +-
 t/t2024-checkout-dwim.sh                      |  70 +--
 t/t2027-checkout-track.sh                     |   6 +-
 t/t2030-unresolve-info.sh                     |   6 +-
 t/t2060-switch.sh                             |  30 +-
 t/t2070-restore.sh                            |   4 +-
 t/t2106-update-index-assume-unchanged.sh      |   2 +-
 t/t2400-worktree-add.sh                       |  66 +--
 t/t2401-worktree-prune.sh                     |   2 +-
 t/t2402-worktree-list.sh                      |  20 +-
 t/t2405-worktree-submodule.sh                 |   6 +-
 t/t3040-subprojects-basic.sh                  |   2 +-
 t/t3200-branch.sh                             | 248 ++++-----
 t/t3201-branch-contains.sh                    |  82 +--
 t/t3202-show-branch-octopus.sh                |   2 +-
 t/t3203-branch-output.sh                      |  40 +-
 t/t3204-branch-name-interpretation.sh         |   6 +-
 t/t3205-branch-color.sh                       |   8 +-
 t/t3206-range-diff.sh                         |  40 +-
 t/t3206/history.export                        |   2 +-
 t/t3210-pack-refs.sh                          |   4 +-
 t/t3211-peel-ref.sh                           |   4 +-
 t/t3301-notes.sh                              |   6 +-
 t/t3302-notes-index-expensive.sh              |   2 +-
 t/t3303-notes-subtrees.sh                     |   8 +-
 t/t3304-notes-mixed.sh                        |   8 +-
 t/t3308-notes-merge.sh                        |   2 +-
 t/t3320-notes-merge-worktrees.sh              |   4 +-
 t/t3400-rebase.sh                             |  60 +--
 t/t3402-rebase-merge.sh                       |  44 +-
 t/t3403-rebase-skip.sh                        |   6 +-
 t/t3405-rebase-malformed.sh                   |   8 +-
 t/t3406-rebase-message.sh                     |  24 +-
 t/t3407-rebase-abort.sh                       |  18 +-
 t/t3408-rebase-multi-line.sh                  |   2 +-
 t/t3409-rebase-preserve-merges.sh             |  10 +-
 t/t3412-rebase-root.sh                        |  28 +-
 t/t3413-rebase-hook.sh                        |  42 +-
 t/t3415-rebase-autosquash.sh                  |   2 +-
 t/t3416-rebase-onto-threedots.sh              |  54 +-
 t/t3418-rebase-continue.sh                    |  24 +-
 t/t3419-rebase-patch-id.sh                    |  12 +-
 t/t3420-rebase-autostash.sh                   |   8 +-
 t/t3423-rebase-reword.sh                      |   6 +-
 t/t3427-rebase-subtree.sh                     |  20 +-
 t/t3430-rebase-merges.sh                      |  16 +-
 t/t3431-rebase-fork-point.sh                  |  32 +-
 t/t3432-rebase-fast-forward.sh                |  34 +-
 t/t3434-rebase-i18n.sh                        |   8 +-
 t/t3435-rebase-gpg-sign.sh                    |   4 +-
 t/t3436-rebase-more-options.sh                |   2 +-
 t/t3500-cherry.sh                             |  12 +-
 t/t3501-revert-cherry-pick.sh                 |   4 +-
 t/t3502-cherry-pick-merge.sh                  |   2 +-
 t/t3503-cherry-pick-root.sh                   |  10 +-
 t/t3504-cherry-pick-rerere.sh                 |  24 +-
 t/t3505-cherry-pick-empty.sh                  |  24 +-
 t/t3506-cherry-pick-ff.sh                     |   8 +-
 t/t3507-cherry-pick-conflict.sh               |   2 +-
 t/t3508-cherry-pick-many-commits.sh           |  38 +-
 t/t3509-cherry-pick-merge-df.sh               |   2 +-
 t/t3512-cherry-pick-submodule.sh              |   2 +-
 t/t3600-rm.sh                                 |  10 +-
 t/t3701-add-interactive.sh                    |   4 +-
 t/t3901-i18n-patch.sh                         |  40 +-
 t/t3903-stash.sh                              |  32 +-
 t/t3910-mac-os-precompose.sh                  |   6 +-
 t/t4014-format-patch.sh                       | 176 +++---
 t/t4015-diff-whitespace.sh                    |   2 +-
 t/t4017-diff-retval.sh                        |   2 +-
 t/t4038-diff-combined.sh                      |  14 +-
 t/t4041-diff-submodule-option.sh              |   2 +-
 t/t4048-diff-combined-binary.sh               |  10 +-
 t/t4052-stat-output.sh                        |   4 +-
 t/t4056-diff-order.sh                         |   2 +-
 t/t4057-diff-combined-paths.sh                |  20 +-
 t/t4061-diff-indent.sh                        |  24 +-
 t/t4066-diff-emit-delay.sh                    |   2 +-
 t/t4068-diff-symmetric-merge-base.sh          |  48 +-
 t/t4103-apply-binary.sh                       |  36 +-
 t/t4108-apply-threeway.sh                     |  14 +-
 t/t4121-apply-diffs.sh                        |   2 +-
 t/t4122-apply-symlink-inside.sh               |   6 +-
 t/t4150-am.sh                                 |  26 +-
 t/t4200-rerere.sh                             |  20 +-
 t/t4201-shortlog.sh                           |   2 +-
 t/t4202-log.sh                                | 106 ++--
 t/t4203-mailmap.sh                            |   2 +-
 t/t4204-patch-id.sh                           |  26 +-
 t/t4207-log-decoration-colors.sh              |   6 +-
 t/t4208-log-magic-pathspec.sh                 |   4 +-
 t/t4211/history.export                        |   2 +-
 t/t4214-log-graph-octopus.sh                  |   2 +-
 t/t4216-log-bloom.sh                          |   4 +-
 t/t4253-am-keep-cr-dos.sh                     |  20 +-
 t/t4257-am-interactive.sh                     |   2 +-
 t/t5150-request-pull.sh                       |  34 +-
 t/t5304-prune.sh                              |   2 +-
 t/t5305-include-tag.sh                        |   2 +-
 t/t5312-prune-corruption.sh                   |  16 +-
 t/t5317-pack-objects-filter-objects.sh        |   2 +-
 t/t5322-pack-objects-sparse.sh                |   2 +-
 t/t5323-pack-redundant.sh                     |  66 +--
 t/t5400-send-pack.sh                          |  60 +--
 t/t5401-update-hooks.sh                       |  24 +-
 t/t5402-post-merge-hook.sh                    |   2 +-
 t/t5403-post-checkout-hook.sh                 |   6 +-
 t/t5404-tracking-branches.sh                  |   8 +-
 t/t5405-send-pack-rewind.sh                   |   6 +-
 t/t5407-post-rewrite-hook.sh                  |   2 +-
 t/t5410-receive-pack-alternates.sh            |   4 +-
 t/t5500-fetch-pack.sh                         |  28 +-
 t/t5501-fetch-push-alternates.sh              |   4 +-
 t/t5502-quickfetch.sh                         |   6 +-
 t/t5503-tagfollow.sh                          |  12 +-
 t/t5504-fetch-receive-strict.sh               |  20 +-
 t/t5505-remote.sh                             | 148 +++---
 t/t5506-remote-groups.sh                      |   4 +-
 t/t5509-fetch-push-namespaces.sh              |  30 +-
 t/t5510-fetch.sh                              | 162 +++---
 t/t5511-refspec.sh                            |  12 +-
 t/t5512-ls-remote.sh                          |  26 +-
 t/t5514-fetch-multiple.sh                     |  30 +-
 t/t5516-fetch-push.sh                         | 500 +++++++++---------
 t/t5517-push-mirror.sh                        | 124 ++---
 t/t5518-fetch-exit-status.sh                  |   6 +-
 t/t5519-push-alternates.sh                    |  12 +-
 t/t5520-pull.sh                               |  30 +-
 t/t5521-pull-options.sh                       |  16 +-
 t/t5523-push-upstream.sh                      |  30 +-
 t/t5526-fetch-submodules.sh                   |  48 +-
 t/t5527-fetch-odd-refs.sh                     |  14 +-
 t/t5528-push-default.sh                       |  98 ++--
 t/t5529-push-errors.sh                        |   2 +-
 t/t5530-upload-pack-error.sh                  |   2 +-
 t/t5531-deep-submodule-push.sh                | 188 +++----
 t/t5533-push-cas.sh                           | 142 ++---
 t/t5534-push-signed.sh                        |   4 +-
 t/t5537-fetch-shallow.sh                      |  30 +-
 t/t5538-push-shallow.sh                       |  22 +-
 t/t5539-fetch-http-shallow.sh                 |  14 +-
 t/t5540-http-push-webdav.sh                   |   8 +-
 t/t5541-http-push-smart.sh                    |  40 +-
 t/t5542-push-http-shallow.sh                  |   8 +-
 t/t5543-atomic-push.sh                        |  80 +--
 t/t5545-push-options.sh                       |  62 +--
 t/t5548-push-porcelain.sh                     |  64 +--
 t/t5550-http-fetch-dumb.sh                    |  20 +-
 t/t5551-http-fetch-smart.sh                   |  20 +-
 t/t5552-skipping-fetch-negotiator.sh          |   2 +-
 t/t5553-set-upstream.sh                       |  82 +--
 t/t5561-http-backend.sh                       |   4 +-
 t/t556x_common                                |   8 +-
 t/t5570-git-daemon.sh                         |  16 +-
 t/t5571-pre-push-hook.sh                      |   4 +-
 t/t5572-pull-submodule.sh                     |   4 +-
 t/t5580-unc-paths.sh                          |   2 +-
 t/t5581-http-curl-verbose.sh                  |   2 +-
 t/t5582-fetch-negative-refspec.sh             |  22 +-
 t/t5601-clone.sh                              |   4 +-
 t/t5604-clone-reference.sh                    |  12 +-
 t/t5605-clone-local.sh                        |  10 +-
 t/t5606-clone-options.sh                      |   8 +-
 t/t5607-clone-bundle.sh                       |  14 +-
 t/t5608-clone-2gb.sh                          |   2 +-
 t/t5609-clone-branch.sh                       |   6 +-
 t/t5610-clone-detached.sh                     |   4 +-
 t/t5611-clone-config.sh                       |  16 +-
 t/t5612-clone-refspec.sh                      |  42 +-
 t/t5614-clone-submodules-shallow.sh           |   2 +-
 t/t5616-partial-clone.sh                      |  50 +-
 t/t5617-clone-submodules-remote.sh            |   6 +-
 t/t5700-protocol-v1.sh                        |  16 +-
 t/t5701-git-serve.sh                          |  16 +-
 t/t5702-protocol-v2.sh                        |  50 +-
 t/t5703-upload-pack-ref-in-want.sh            |  60 +--
 t/t5801-remote-helpers.sh                     |  24 +-
 t/t6000-rev-list-misc.sh                      |   2 +-
 t/t6001-rev-list-graft.sh                     |   2 +-
 t/t6004-rev-list-path-optim.sh                |  14 +-
 t/t6006-rev-list-format.sh                    |  14 +-
 t/t6007-rev-list-cherry-pick-file.sh          |   4 +-
 t/t6008-rev-list-submodule.sh                 |   2 +-
 t/t6009-rev-list-parent.sh                    |   6 +-
 t/t6012-rev-list-simplify.sh                  |   8 +-
 t/t6013-rev-list-reverse-parents.sh           |  10 +-
 t/t6016-rev-list-graph-simplify-history.sh    |   2 +-
 t/t6017-rev-list-stdin.sh                     |   8 +-
 t/t6018-rev-list-glob.sh                      |  50 +-
 t/t6019-rev-list-ancestry-path.sh             |   6 +-
 t/t6030-bisect-porcelain.sh                   |  10 +-
 t/t6040-tracking-info.sh                      |  54 +-
 t/t6050-replace.sh                            |  10 +-
 t/t6101-rev-parse-parents.sh                  |   2 +-
 t/t6110-rev-list-sparse.sh                    |   2 +-
 t/t6111-rev-list-treesame.sh                  |   6 +-
 t/t6112-rev-list-filters-objects.sh           |  14 +-
 t/t6120-describe.sh                           |  20 +-
 t/t6200-fmt-merge-msg.sh                      |  50 +-
 t/t6302-for-each-ref-filter.sh                |  58 +-
 t/t6400-merge-df.sh                           |   6 +-
 t/t6402-merge-rename.sh                       |  46 +-
 t/t6404-recursive-merge.sh                    |   4 +-
 t/t6405-merge-symlinks.sh                     |  14 +-
 t/t6406-merge-attr.sh                         |  24 +-
 t/t6407-merge-binary.sh                       |   6 +-
 t/t6409-merge-subtree.sh                      |  16 +-
 t/t6411-merge-filemode.sh                     |  10 +-
 t/t6412-merge-large-rename.sh                 |   6 +-
 t/t6413-merge-crlf.sh                         |   2 +-
 t/t6414-merge-rename-nocruft.sh               |   2 +-
 t/t6415-merge-dir-to-symlink.sh               |  22 +-
 t/t6416-recursive-corner-cases.sh             |  28 +-
 t/t6417-merge-ours-theirs.sh                  |  28 +-
 t/t6418-merge-text-auto.sh                    |  12 +-
 t/t6419-merge-ignorecase.sh                   |  10 +-
 t/t6422-merge-rename-corner-cases.sh          |  12 +-
 t/t6425-merge-rename-delete.sh                |   2 +-
 t/t6427-diff3-conflict-markers.sh             |  14 +-
 t/t6430-merge-recursive.sh                    |  18 +-
 t/t6432-merge-recursive-space-options.sh      |   6 +-
 t/t6433-merge-toplevel.sh                     |   8 +-
 t/t6434-merge-recursive-rename-options.sh     |   6 +-
 t/t6436-merge-overwrite.sh                    |   2 +-
 t/t6437-submodule-merge.sh                    |  14 +-
 t/t6439-merge-co-error-msgs.sh                |   6 +-
 t/t6501-freshen-objects.sh                    |   2 +-
 t/t7003-filter-branch.sh                      |  40 +-
 t/t7004-tag.sh                                |   8 +-
 t/t7030-verify-tag.sh                         |   2 +-
 t/t7060-wtstatus.sh                           |  26 +-
 t/t7063-status-untracked-cache.sh             |  14 +-
 t/t7102-reset.sh                              |   6 +-
 t/t7113-post-index-change-hook.sh             |   2 +-
 t/t7201-co.sh                                 | 110 ++--
 t/t7400-submodule-basic.sh                    |  20 +-
 t/t7403-submodule-sync.sh                     |  10 +-
 t/t7406-submodule-update.sh                   |  38 +-
 t/t7407-submodule-foreach.sh                  |  24 +-
 t/t7409-submodule-detached-work-tree.sh       |   8 +-
 t/t7417-submodule-path-url.sh                 |   2 +-
 t/t7501-commit-basic-functionality.sh         |   2 +-
 t/t7502-commit-porcelain.sh                   |  12 +-
 ...3-pre-commit-and-pre-merge-commit-hooks.sh |  42 +-
 t/t7504-commit-msg-hook.sh                    |  24 +-
 t/t7505-prepare-commit-msg-hook.sh            |  20 +-
 t/t7508-status.sh                             |  58 +-
 t/t7510-signed-commit.sh                      |   2 +-
 t/t7512-status-help.sh                        |  40 +-
 t/t7517-per-repo-email.sh                     |  12 +-
 t/t7600-merge.sh                              |  44 +-
 t/t7606-merge-custom.sh                       |   2 +-
 t/t7608-merge-messages.sh                     |  36 +-
 t/t7610-mergetool.sh                          | 174 +++---
 t/t7611-merge-abort.sh                        |   4 +-
 t/t7612-merge-verify-signatures.sh            |   2 +-
 t/t7614-merge-signoff.sh                      |  24 +-
 t/t7701-repack-unpack-unreachable.sh          |   2 +-
 t/t7800-difftool.sh                           |  38 +-
 t/t7810-grep.sh                               |  28 +-
 t/t8001-annotate.sh                           |   2 +-
 t/t8003-blame-corner-cases.sh                 |   4 +-
 t/t8004-blame-with-conflicts.sh               |  14 +-
 t/t9001-send-email.sh                         |  28 +-
 t/t9100-git-svn-basic.sh                      |   2 +-
 t/t9145-git-svn-master-branch.sh              |   6 +-
 t/t9151-svn-mergeinfo.sh                      |   2 +-
 t/t9155-git-svn-fetch-deleted-tag.sh          |   2 +-
 t/t9156-git-svn-fetch-deleted-tag-2.sh        |   6 +-
 t/t9163-git-svn-reset-clears-caches.sh        |   2 +-
 t/t9169-git-svn-dcommit-crlf.sh               |   2 +-
 t/t9300-fast-import.sh                        |  82 +--
 t/t9301-fast-import-notes.sh                  |  14 +-
 t/t9302-fast-import-unpack-limit.sh           |  16 +-
 t/t9350-fast-export.sh                        |  86 +--
 t/t9351-fast-export-anonymize.sh              |   4 +-
 t/t9400-git-cvsserver-server.sh               |  32 +-
 t/t9401-git-cvsserver-crlf.sh                 |  16 +-
 t/t9402-git-cvsserver-refs.sh                 |   8 +-
 t/t9500-gitweb-standalone-no-errors.sh        |  20 +-
 t/t9501-gitweb-standalone-http-status.sh      |  14 +-
 t/t9502-gitweb-standalone-parse-output.sh     |  16 +-
 t/t9600-cvsimport.sh                          |   2 +-
 t/t9601-cvsimport-vendor-branch.sh            |  16 +-
 t/t9602-cvsimport-branches-tags.sh            |   4 +-
 t/t9603-cvsimport-patchsets.sh                |   8 +-
 t/t9800-git-p4-basic.sh                       |   2 +-
 t/t9801-git-p4-branch.sh                      |  16 +-
 t/t9806-git-p4-options.sh                     |  18 +-
 t/t9807-git-p4-submit.sh                      |   2 +-
 t/t9811-git-p4-label-import.sh                |   2 +-
 t/t9903-bash-prompt.sh                        | 114 ++--
 t/test-lib.sh                                 |  13 +
 351 files changed, 3903 insertions(+), 3890 deletions(-)


base-commit: aff20da3a209088e7f8f3632077fa11b86453d67
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-762%2Fdscho%2Fuse-main-as-default-branch-name-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-762/dscho/use-main-as-default-branch-name-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/762

Comments

Felipe Contreras Nov. 13, 2020, 12:11 a.m. UTC | #1
On Thu, Nov 12, 2020 at 5:55 PM Johannes Schindelin via GitGitGadget
<gitgitgadget@gmail.com> wrote:

> This is the big one. This changes the default of init.defaultBranch to main,
> reflecting what many open source projects already did (which was followed by
> GitHub, Azure Repos and others).

I want to plant a big red flag here for the record.

I am against this change.

At the very least in the manner it is being made. I started a separate
thread [1] explaining the reasoning.

In addition to the manner--which I argue in that other thread should
be done for Git 3.0--I also object to the reasoning behind the change.

Let me know if you would rather hear my arguments against the
reasoning here, or in the other thread.

Cheers.

[1] https://lore.kernel.org/git/CAMP44s3BJ3dGsLJ-6yA-Po459=+m826KD9an4+P3qOY1vkbxZg@mail.gmail.com/
Ævar Arnfjörð Bjarmason Nov. 13, 2020, 12:55 p.m. UTC | #2
On Thu, Nov 12 2020, Johannes Schindelin via GitGitGadget wrote:

> This is the big one. This changes the default of init.defaultBranch to main,
> reflecting what many open source projects already did (which was followed by
> GitHub, Azure Repos and others).

I don't have an issue with the end goal of s/master/main|$whatever/ as
UX here as noted in previous related review rounds. But I don't think
this series as it stands is anywhere near ready.

This is 27 patches of s/master/main/ in the tests, followed by making
the change to the default in refs.c without as much as a single
documentation update to inform users of the change.

I don't see the point in doing these sorts of test suite changes, it
just seems like needless churn. But I have not read the whole backlog of
previous iterations of this & related patches, so bear with me.

Why not instead do what we did when we added protocol v2 to the tests,
e.g. in 8a1b0978ab ("test: request GIT_TEST_PROTOCOL_VERSION=0 when
appropriate", 2019-12-23) we simply set the t5515 test to always run
with protocol v1. If you'd do this:
    
    diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
    index 70a9d2d8ab..939c8b2f83 100755
    --- a/t/t5515-fetch-merge-logic.sh
    +++ b/t/t5515-fetch-merge-logic.sh
    @@ -11,6 +11,9 @@ test_description='Merge logic in fetch'
     GIT_TEST_PROTOCOL_VERSION=0
     export GIT_TEST_PROTOCOL_VERSION
     
    +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
    +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    +
     . ./test-lib.sh
     
     build_script () {
    
Of course that also needs:
    
    index fa347ed3e1..2d700a171b 100644
    --- a/t/test-lib.sh
    +++ b/t/test-lib.sh
    @@ -1711,10 +1711,8 @@ test_lazy_prereq SHA1 '
     test_lazy_prereq REBASE_P '
     	test -z "$GIT_TEST_SKIP_REBASE_P"
     '
    -# Special-purpose prereq for transitioning to a new default branch name:
    -# Some tests need more than just a mindless (case-preserving) s/master/main/g
    -# replacement. The non-trivial adjustments are guarded behind this
    -# prerequisite, acting kind of as a feature flag
    -test_lazy_prereq PREPARE_FOR_MAIN_BRANCH '
    -	test "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" = main
    +
    +test_lazy_prereq MAIN_BRANCH_IS_MASTER '
    +	test -z "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" ||
    +	test "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" = "master"
     '

Because (but see "later" a few paragraphs later), the logic as it stands
on "master" is entirely backwards & broken. I.e. if you don't set
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME or set it to "master" we now skip a
bunch of tests ... which only work if the value is "master". If you set
it to "main" they'll break.

Then instead of ending up with a hardcoding of "main" we'd be able to
run the tests with a new custom branch name (even one with whitespace in
it). That coverage is plenty to test any branch name hardcoding.

The remaining tests that would still have "master" would then just be
dealt with by the same thing we did for the too-protocol-v1-specific
tests, i.e.:
    
    diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh
    index 8b635a196d..354f9bd851 100755
    --- a/t/t3502-cherry-pick-merge.sh
    +++ b/t/t3502-cherry-pick-merge.sh
    @@ -8,6 +8,8 @@ test_description='cherry picking and reverting a merge
     
     '
     
    +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
    +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
     . ./test-lib.sh
     
     test_expect_success setup '
    
Except unlike protocol v1/v2 we're really not gaining anything in
coverage by going further, it's not the point of any of these tests to
test for the default branch name. It's a *lot* of churn, 

"Later": After writing the above I see from 704fed9ea2 ("tests: start
moving to a different default main branch name", 2020-10-23) that this
state of affairs is intentional. But doesn't discuss why the more usual
(because we've done it that way a few times before) v1/v2-esque
transition wasn't done instead.

Doing it the other way still seems better. We're now not running our
full tests in anticipation for this series landing on "master", and
after applying this we're still not running all of them.

Anyway, enough with discussing this detail of the test suite churn. My
main objection to this version of it is:

After this series as it stands lands what's a rather big UI change in
git isn't discussed *anywhere* in the docs.

I'm not saying we need some similar s/master/main/g in Documentation/ as
what's being done here in t/, but I think a bare minimum for a rather
big UI change like this is:

 1) Let's at least talk about it in some way in git-init(1), i.e. that
    it used to be "master" before version so-and-so and is now
    different. With this series applied we still say:

    Documentation/git-init.txt:If not specified, fall back to the default name: `master`.

 2) Ditto in the init.defaultBranch and things like that

 3) After all this effort at eliminating "master" entirely in the tests
    we're still shipping a sample hook that expects "master" on "git
    init", and breaks now that it's "main"

And maybe stuff like:

 4) Have "git init" emit some new advice message saying that the default
    has changed and we've init-ed a new repo with a "main" branch.

Our primary concern should be the vast majority of users who don't
follow this topic on Twitter, don't read this mailing list, and are just
going to waste 10 minutes of their day because some script they've had
working for years using "git init" did something unexpected.

Let's at least aim to make that 5 minutes instead by making the change
more discoverable.
Johannes Schindelin Nov. 13, 2020, 2:22 p.m. UTC | #3
Hi Ævar,

On Fri, 13 Nov 2020, Ævar Arnfjörð Bjarmason wrote:

> On Thu, Nov 12 2020, Johannes Schindelin via GitGitGadget wrote:
>
> > This is the big one. This changes the default of init.defaultBranch to main,
> > reflecting what many open source projects already did (which was followed by
> > GitHub, Azure Repos and others).
>
> I don't have an issue with the end goal of s/master/main|$whatever/ as
> UX here as noted in previous related review rounds. But I don't think
> this series as it stands is anywhere near ready.
>
> This is 27 patches of s/master/main/ in the tests, followed by making
> the change to the default in refs.c without as much as a single
> documentation update to inform users of the change.

Of course, this is _the one_ patch series mentioned in
https://github.com/gitgitgadget/git/pull/655 that does _not_ link back to
the meta-PR.

So you're right, on its own, these 28 patches do not make sense.

And if you split off the 28th patch, the remaining 27 patches make even
less sense.

The reason why I partitioned the changes this way was that it is a _ton_
of patches to review, and in many ways, these 28 patches are the most
important ones to review (I didn't want to just rely on the CI builds
passing, I reviewed those patches carefully, multiple times, to make sure
that they made sense in the goal to transition to `main`).

I will respond to the rest of your concerns later,
Dscho

>
> I don't see the point in doing these sorts of test suite changes, it
> just seems like needless churn. But I have not read the whole backlog of
> previous iterations of this & related patches, so bear with me.
>
> Why not instead do what we did when we added protocol v2 to the tests,
> e.g. in 8a1b0978ab ("test: request GIT_TEST_PROTOCOL_VERSION=0 when
> appropriate", 2019-12-23) we simply set the t5515 test to always run
> with protocol v1. If you'd do this:
>
>     diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
>     index 70a9d2d8ab..939c8b2f83 100755
>     --- a/t/t5515-fetch-merge-logic.sh
>     +++ b/t/t5515-fetch-merge-logic.sh
>     @@ -11,6 +11,9 @@ test_description='Merge logic in fetch'
>      GIT_TEST_PROTOCOL_VERSION=0
>      export GIT_TEST_PROTOCOL_VERSION
>
>     +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
>     +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>     +
>      . ./test-lib.sh
>
>      build_script () {
>
> Of course that also needs:
>
>     index fa347ed3e1..2d700a171b 100644
>     --- a/t/test-lib.sh
>     +++ b/t/test-lib.sh
>     @@ -1711,10 +1711,8 @@ test_lazy_prereq SHA1 '
>      test_lazy_prereq REBASE_P '
>      	test -z "$GIT_TEST_SKIP_REBASE_P"
>      '
>     -# Special-purpose prereq for transitioning to a new default branch name:
>     -# Some tests need more than just a mindless (case-preserving) s/master/main/g
>     -# replacement. The non-trivial adjustments are guarded behind this
>     -# prerequisite, acting kind of as a feature flag
>     -test_lazy_prereq PREPARE_FOR_MAIN_BRANCH '
>     -	test "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" = main
>     +
>     +test_lazy_prereq MAIN_BRANCH_IS_MASTER '
>     +	test -z "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" ||
>     +	test "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" = "master"
>      '
>
> Because (but see "later" a few paragraphs later), the logic as it stands
> on "master" is entirely backwards & broken. I.e. if you don't set
> GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME or set it to "master" we now skip a
> bunch of tests ... which only work if the value is "master". If you set
> it to "main" they'll break.
>
> Then instead of ending up with a hardcoding of "main" we'd be able to
> run the tests with a new custom branch name (even one with whitespace in
> it). That coverage is plenty to test any branch name hardcoding.
>
> The remaining tests that would still have "master" would then just be
> dealt with by the same thing we did for the too-protocol-v1-specific
> tests, i.e.:
>
>     diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh
>     index 8b635a196d..354f9bd851 100755
>     --- a/t/t3502-cherry-pick-merge.sh
>     +++ b/t/t3502-cherry-pick-merge.sh
>     @@ -8,6 +8,8 @@ test_description='cherry picking and reverting a merge
>
>      '
>
>     +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
>     +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>      . ./test-lib.sh
>
>      test_expect_success setup '
>
> Except unlike protocol v1/v2 we're really not gaining anything in
> coverage by going further, it's not the point of any of these tests to
> test for the default branch name. It's a *lot* of churn,
>
> "Later": After writing the above I see from 704fed9ea2 ("tests: start
> moving to a different default main branch name", 2020-10-23) that this
> state of affairs is intentional. But doesn't discuss why the more usual
> (because we've done it that way a few times before) v1/v2-esque
> transition wasn't done instead.
>
> Doing it the other way still seems better. We're now not running our
> full tests in anticipation for this series landing on "master", and
> after applying this we're still not running all of them.
>
> Anyway, enough with discussing this detail of the test suite churn. My
> main objection to this version of it is:
>
> After this series as it stands lands what's a rather big UI change in
> git isn't discussed *anywhere* in the docs.
>
> I'm not saying we need some similar s/master/main/g in Documentation/ as
> what's being done here in t/, but I think a bare minimum for a rather
> big UI change like this is:
>
>  1) Let's at least talk about it in some way in git-init(1), i.e. that
>     it used to be "master" before version so-and-so and is now
>     different. With this series applied we still say:
>
>     Documentation/git-init.txt:If not specified, fall back to the default name: `master`.
>
>  2) Ditto in the init.defaultBranch and things like that
>
>  3) After all this effort at eliminating "master" entirely in the tests
>     we're still shipping a sample hook that expects "master" on "git
>     init", and breaks now that it's "main"
>
> And maybe stuff like:
>
>  4) Have "git init" emit some new advice message saying that the default
>     has changed and we've init-ed a new repo with a "main" branch.
>
> Our primary concern should be the vast majority of users who don't
> follow this topic on Twitter, don't read this mailing list, and are just
> going to waste 10 minutes of their day because some script they've had
> working for years using "git init" did something unexpected.
>
> Let's at least aim to make that 5 minutes instead by making the change
> more discoverable.
>
Felipe Contreras Nov. 13, 2020, 5:42 p.m. UTC | #4
On Fri, Nov 13, 2020 at 7:00 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> On Thu, Nov 12 2020, Johannes Schindelin via GitGitGadget wrote:

> After this series as it stands lands what's a rather big UI change in
> git isn't discussed *anywhere* in the docs.
>
> I'm not saying we need some similar s/master/main/g in Documentation/ as
> what's being done here in t/, but I think a bare minimum for a rather
> big UI change like this is:

Why not?

Isn't this change being championed on behalf of users who find the
word offensive?

Why would it be offensive to see the word on the commands you type on
the command line, but not offensive if the documentation tells you to
type those commands? This does not compute.

And worse; for the rest of the users that don't find the word
offensive (99.9% of them?), the documentation is left in an
inconsistent state, where some commands would not work as they are
stated.

If a word is so offensive it has to be erased from the Git lexicon,
then it has to be erased *everywhere*, or at least everywhere a user
might look.

Cheers.
Junio C Hamano Nov. 14, 2020, 6:13 a.m. UTC | #5
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> This is the big one. This changes the default of init.defaultBranch to main,
> reflecting what many open source projects already did (which was followed by
> GitHub, Azure Repos and others).

I'll keep this brief as I'm still offline/vacation til next week.

As other people already said, I'd prefer to see

 - all tests updated to work, without losing any coverage,
   regardless of the default for the init.defaultbranch is.  

   Some test scripts may require setting init.defaultBranch='master'
   at the top in the 'setup' part (I've shown how in my response to
   t4013 patchset) if the body of the test relies too heavily on the
   primary branch to be 'master'.  On the other hand, some test
   scripts may require setting init.defaultBranch='main' at the top,
   if they have been converted to work _only_ with 'main'.

   Both of these are unfortunate, but it is much better than losing
   test coverage during the test update effort.

   Some test scripts may not need any "this test would only work
   with 'master|main', so we are forcing".  After your test update
   series so far, hopefully many may already be ready to be force to
   'main' even when the Git binary may still use 'master' as the
   fallback default for init.defaultBranch.

 - a well thought-out transition plan (including user education and
   publicity), with the final "flip of the fallback default".

and I'd strongly prefer that these two to be done separately.  Since
we cannot anticipate how long the latter would take with unknown
amount of distraction, I'd prefer 100% of our tests keep working
while the fallback default for init.defaultBranch is 'master', and
they still work on the flag day when the default is changed to 'main'
(or 'primary' for that matter---after all, tests that care too deeply
what the primary branch name is, and have been updated to eradicate
'master' from them, would be forcing 'main', so the hardcoded
fallback default in our binary should not matter).

Thanks.
Junio C Hamano Nov. 16, 2020, 7:52 p.m. UTC | #6
Junio C Hamano <gitster@pobox.com> writes:

>    Some test scripts may require setting init.defaultBranch='master'
>    at the top in the 'setup' part (I've shown how in my response to
>    t4013 patchset) if the body of the test relies too heavily on the
>    primary branch to be 'master'.

Ah, I realized we have much better mechanism already in the form of
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME environment.

So, my three wishes in this message now become

 - lose PREPARE_FOR_MAIN_BRANCH prerequisite as quickly as possible
   by doing the following two.

 - Use that mechanism to force 'main' in test scripts that now only
   can work with 'main', even before we change the fallback default
   from master to main in the production code, so that we won't lose
   test coverage.

 - The same for test scripts that are not converted yet to force use
   of 'master', so that we could change the fallback default from
   master to main in the production code even before converting
   these other scripts, so that we won't lose test coverage.

Thanks.
Johannes Schindelin Nov. 17, 2020, 4:10 p.m. UTC | #7
Hi Junio,

On Mon, 16 Nov 2020, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
>
> >    Some test scripts may require setting init.defaultBranch='master'
> >    at the top in the 'setup' part (I've shown how in my response to
> >    t4013 patchset) if the body of the test relies too heavily on the
> >    primary branch to be 'master'.
>
> Ah, I realized we have much better mechanism already in the form of
> GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME environment.
>
> So, my three wishes in this message now become
>
>  - lose PREPARE_FOR_MAIN_BRANCH prerequisite as quickly as possible

Okay, we're on the same page here.

>    by doing the following two.

A couple of test cases already have the `PREPARE_FOR_MAIN_BRANCH` prereq
(in preparation for transitioning the test suite, which is what I will
settle for in v2 of this patch series). Most notably, t5526 and t9902,
which I had to exclude to avoid clashing with branches that are currently
in flight.

So my goal is to transition the test suite as quickly as possible, by
first converting the majority in v2 of this patch series, and then
handling the rest of the test scripts individually, on top of the
in-flight topics.

>  - Use that mechanism to force 'main' in test scripts that now only
>    can work with 'main', even before we change the fallback default
>    from master to main in the production code, so that we won't lose
>    test coverage.

That's precisely what I do, incrementally, by adjusting that `case`
statement in `t/test-lib.sh` whenever a range of test scripts has been
transitioned. In patch 2/28, it looks like this:

	case "$TEST_NUMBER" in
	[01]*)
	       GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
	       export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
	       ;;
	esac

By patch 26/28, it looks like this:

	case "$TEST_NUMBER" in
	3404|4013|5310|5526|6300|7064|7817|9902)
		# Avoid conflicts with patch series that are cooking at the same
		# time
		# as the patch series changing the default of
		# `init.defaultBranch`.
		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
		;;
	*)
		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
		;;
	esac

>  - The same for test scripts that are not converted yet to force use
>    of 'master', so that we could change the fallback default from
>    master to main in the production code even before converting
>    these other scripts, so that we won't lose test coverage.

Okay, I could have done it that way by starting with

	case "$TEST_NUMBER" in
	[01]*)
		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
		;;
	*)
		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
		;;
	esac

But that would result in a funny-looking intermediate state with a
`master` arm, then `main`, then again `master`.

Besides, it would be more complicated because t/t5411-proc-receive-hook.sh
and t/t5515-fetch-merge-logic.sh already ask for `main`, but by setting it
before sourcing `test-lib.sh`, and therefore we would have to special-case
them in that `case` from the get-go.

Therefore, in the interest of making this patch series _slightly_ easier
to review (you still have to look at the _bottom_ of most of those patches
to catch the crucial change to `t/test-lib.sh`), I would like to keep the
patch series in the current shape.

Will send v2 in a moment.

Thanks,
Dscho
Junio C Hamano Nov. 17, 2020, 7:09 p.m. UTC | #8
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Hi Junio,
>
> On Mon, 16 Nov 2020, Junio C Hamano wrote:
>
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>> >    Some test scripts may require setting init.defaultBranch='master'
>> >    at the top in the 'setup' part (I've shown how in my response to
>> >    t4013 patchset) if the body of the test relies too heavily on the
>> >    primary branch to be 'master'.
>>
>> Ah, I realized we have much better mechanism already in the form of
>> GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME environment.
>>
>> So, my three wishes in this message now become
>>
>>  - lose PREPARE_FOR_MAIN_BRANCH prerequisite as quickly as possible
>
> Okay, we're on the same page here.

Yeah, you may have noticed after reading my recent messages to this
topic, my initial reaction was mostly triggered by "eh, are we
losing test coverage too much?" before re-reading what the patches
(both what we have already merged and these 28 final stretch
patches) actually do, and realizing that they aim at preparing us so
that we can flip the fallback default any time we like.  So we are
very much on the same page.

> That's precisely what I do, incrementally, by adjusting that `case`
> statement in `t/test-lib.sh` whenever a range of test scripts has been
> transitioned. In patch 2/28, it looks like this:
>
> 	case "$TEST_NUMBER" in
> 	[01]*)
> 	       GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> 	       export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> 	       ;;
> 	esac
>
> By patch 26/28, it looks like this:
>
> 	case "$TEST_NUMBER" in
> 	3404|4013|5310|5526|6300|7064|7817|9902)
> 		# Avoid conflicts with patch series that are cooking at the same
> 		# time
> 		# as the patch series changing the default of
> 		# `init.defaultBranch`.
> 		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
> 		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> 		;;
> 	*)
> 		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> 		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> 		;;
> 	esac

I actually am not a big fan of the centralized table of "these want
to run with main".  My ideal would be to have an explicit assignment
of either master or main for tests that absolutely require the
default to be one of these names at the top of these script, and any
test scripts that do not care what the initial branch is called
(perhaps because they begin by switching to a branch whose name is
picked by them immediately after they start and use that name
throughout) won't have GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME in them.

I think we can live with a centralized "case", but I have trouble
with seeing only two arms in the above case statement, whether which
one gets the asterisk.  There may be ones that need to force
'master', there may be ones that need to force 'main', but hopefully
many do not even have to force and can work with either.  And seeing
"everything else works only with 'main'" is a bit disappointing.

But if you must have a case with only two arms, i.e. "these are
exceptions" and "everything else", I think the above (i.e. we
refrain from touching these and force them to 'master' as
exceptions, but everything else is forced to 'main') is better than
having them the other way around.

Thanks.
Eric W. Biederman Nov. 17, 2020, 8:48 p.m. UTC | #9
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:

> This is the big one. This changes the default of init.defaultBranch to main,
> reflecting what many open source projects already did (which was followed by
> GitHub, Azure Repos and others).

Can we please not simply replace one hard coded branch name with
another?

Having a blessed name for the initially created branch continues to
imply the branch has special significance.  As the initially created
branch does not have special significance can we please do
something that does not imply that?

Instead of having a fixed name across all repos for the initially
created branch can we instead use the directory name of the repo for the
branch name?

Advantages:

- The branch name that is somewhat meaningful to the creator of the git
  repo.

  I have at least two repos where I wound up doing this by hand.  So at
  least for me it is something I am doing anyway.

- Tools can not hard code the name of an initially created branch and
  expect it to work.

  This moves us farther from the realm of people assuming incorrectly
  that there is something special about the branch created by default.

- As the name is somewhat meaningful.  This change to the initial branch
  name becomes something that can be argued is a technical improvement
  rather than a simple political statement.

At least for my usage main is a pretty huge misnomer as I barely use the
branch with the master.  Renaming my unused branch main implies that I
am using the tool wrong.


I don't look in on the git list very often so perhaps I am missing a
conversation where all of the details were thought through.  If so
please point me at that conversation.  Otherwise can we please use this
opportunity to come up with something that is actually better than
naming the default branch main, rather than just something just as
awkward whose only advantage is that people don't think it is
politically incorrect this week.

Eric
Felipe Contreras Nov. 17, 2020, 10:47 p.m. UTC | #10
On Tue, Nov 17, 2020 at 3:10 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > This is the big one. This changes the default of init.defaultBranch to main,
> > reflecting what many open source projects already did (which was followed by
> > GitHub, Azure Repos and others).
>
> Can we please not simply replace one hard coded branch name with
> another?

I thought precisely the same thing.

This should be easy to do if we make "origin" be a pseudo ref that
points to "origin/HEAD" (and we could introduce "origin/@").

That way there will never be a need to type "origin/master", or having
it as an upstream, you can simply set "origin" as the upstream
tracking "branch".

> I don't look in on the git list very often so perhaps I am missing a
> conversation where all of the details were thought through.  If so
> please point me at that conversation.  Otherwise can we please use this
> opportunity to come up with something that is actually better than
> naming the default branch main, rather than just something just as
> awkward whose only advantage is that people don't think it is
> politically incorrect this week.

This is the thread:

https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/

Unfortunately in my opinion the most important topics--like your
suggestion--were not even mentioned. Everyone focused on the wrong
thing (e.g. what would be a better name for "master").

Cheers.
Junio C Hamano Nov. 17, 2020, 10:55 p.m. UTC | #11
ebiederm@xmission.com (Eric W. Biederman) writes:

> "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> This is the big one. This changes the default of init.defaultBranch to main,
>> reflecting what many open source projects already did (which was followed by
>> GitHub, Azure Repos and others).
>
> Can we please not simply replace one hard coded branch name with
> another?
>
> Having a blessed name for the initially created branch continues to
> imply the branch has special significance.  As the initially created
> branch does not have special significance can we please do
> something that does not imply that?

I personally am fond of this line of "let's not treat one single
thing any special among others" approach, but I think the way people
use the initially created branch tends to make it special at the end
of the day.

While the project is still in its infancy, you may use that as the
only branch until the tree of the project starts to take its shape,
perhaps with subdirectories dedicated to sources, documentation, and
overall build procedure, etc.  Then you may start to fork different
branches to work on topics that last more than one commit's worth of
time and then it is likely you'd use the initially created branch as
the integration branch, until you start to need the second and third
integration branches.  Like it or not, the primary integration
branch would inevitably end up being something more special than
others, and it is likely that using the initially created branch for
that purpose would be the most convenient.  There however may exist
two or more equally significant branches, not just one special one,
though, but it is reasonable to have at least one special one.

I think using some word that is derived from $(basename $(pwd)) as
the name of the initial branch may be a more reasonable choice than
using any single word that tries to fit everybody (which will *not*
exist).  When a user says "git init tinyshell" to start a project to
create a tiny shell, "tinyshell" may be one reasonable choice to
refer to its primary integration branch.  Everything that goes into
it will become part of the tinyshell project.

But if there is a woke-safe word that can refer to "the primary
integration branch", calling the initially created branch with that
word by default is also equally a reasonable approach.  I personally
do not like the word 'main' used as such, but the rest of the world
seems to be moving in that direction, so being consistent with them
would help users who want to do

	mkdir project && cd project
	git init
	... some workflow specific 'git config' here ...
	git remote add $URL origin
	git pull origin

and have it be an enhanced equivalent to

	git clone $URL project

The latter will try to find the name used for the primary branch on
the other side and use the same name; the former would not work that
way, but if "git init" uses a fallback default that is most common,
it would hurt less.

In any case, the updated version of these 28 patches no longer has
the final "switch the fallback default to 'main'" step, and the good
thing is that the other 27 patches will help us moving in any
direction.  If we choose to dynamically derive the initial branch
name, these steps make sure that such a change won't break our
testsuite.

> Instead of having a fixed name across all repos for the initially
> created branch can we instead use the directory name of the repo for the
> branch name?
>
> Advantages:
>
> - The branch name that is somewhat meaningful to the creator of the git
>   repo.
>
>   I have at least two repos where I wound up doing this by hand.  So at
>   least for me it is something I am doing anyway.

Direct "other side" of the coin is that the name meaningful to the
creator may be different from project to project, so those who want
to try peeking projects that are so far unknown to them will have to
guess what that meaningful thing is.  When visiting a random github
repository and presented by 47 different branches, it would be more
helpful for such a visitor to have a reliable "this is likely to be
the primary integration branch" cue.  Not having a convention is
worse than having a convention some folks may find suboptimal from
usability's point of view.

> - Tools can not hard code the name of an initially created branch and
>   expect it to work.

Cannot?  Is this a dogmatic declaration?

If tools that are meant to work with variety of projects with a
single "special" branch and do things relative to that special
branch (e.g. perhaps the special branch is the primary integration
branch, and the tool may list commits that are not yet in that
branch), a toolsmith has multiple choices.  The tool can take the
name of the "special" branch from the end-user to be most flexible,
of the tool can hardcode the most commonly used name for the
"special" branch to be out-of-the-box useful for majority of
projects.  Most sensible folks may do the former, but I do not think
the latter is a bad choice.  And even those who do the former has to
fall back to some hardcoded value when the user didn't give the name
of the "special" branch, because end-users are greedy and will
demand such a "convenience" feature, saying "in most repositories,
this name is commonly used for the 'special' branch---why force us
to type the same thing?"
Felipe Contreras Nov. 17, 2020, 11:16 p.m. UTC | #12
On Tue, Nov 17, 2020 at 4:57 PM Junio C Hamano <gitster@pobox.com> wrote:
> ebiederm@xmission.com (Eric W. Biederman) writes:

> > - The branch name that is somewhat meaningful to the creator of the git
> >   repo.
> >
> >   I have at least two repos where I wound up doing this by hand.  So at
> >   least for me it is something I am doing anyway.
>
> Direct "other side" of the coin is that the name meaningful to the
> creator may be different from project to project, so those who want
> to try peeking projects that are so far unknown to them will have to
> guess what that meaningful thing is.  When visiting a random github
> repository and presented by 47 different branches, it would be more
> helpful for such a visitor to have a reliable "this is likely to be
> the primary integration branch" cue.  Not having a convention is
> worse than having a convention some folks may find suboptimal from
> usability's point of view.

But a convention is just that: a convention.

If we already know "origin/HEAD" is very likely pointing to the
integration branch, then why do we need to know what that branch is
called in that particular project?

Just refer to that branch as "origin/@", or just "origin".

That would work for projects that follow the convention, and those who
don't. Why does the tool need to care?

Cheers.
Jeff King Nov. 17, 2020, 11:33 p.m. UTC | #13
On Tue, Nov 17, 2020 at 04:47:56PM -0600, Felipe Contreras wrote:

> On Tue, Nov 17, 2020 at 3:10 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
> >
> > "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes:
> >
> > > This is the big one. This changes the default of init.defaultBranch to main,
> > > reflecting what many open source projects already did (which was followed by
> > > GitHub, Azure Repos and others).
> >
> > Can we please not simply replace one hard coded branch name with
> > another?
> 
> I thought precisely the same thing.
> 
> This should be easy to do if we make "origin" be a pseudo ref that
> points to "origin/HEAD" (and we could introduce "origin/@").

Didn't we already do this long ago? refs/remotes/%s/HEAD is special in
the dwim_ref() lookup:

  $ git rev-parse --symbolic-full-name origin
  refs/remotes/origin/master

Or did you have something else in mind?

I think I have occasionally hit spots where saying "origin" instead of
"origin/master" does not work. I can't think of any offhand now, though
(I thought perhaps "git checkout -b foo origin" or "git branch
--set-upstream-to=origin", but both seem to work).

> > I don't look in on the git list very often so perhaps I am missing a
> > conversation where all of the details were thought through.  If so
> > please point me at that conversation.  Otherwise can we please use this
> > opportunity to come up with something that is actually better than
> > naming the default branch main, rather than just something just as
> > awkward whose only advantage is that people don't think it is
> > politically incorrect this week.
> 
> This is the thread:
> 
> https://lore.kernel.org/git/CAOAHyQwyXC1Z3v7BZAC+Bq6JBaM7FvBenA-1fcqeDV==apdWDg@mail.gmail.com/
> 
> Unfortunately in my opinion the most important topics--like your
> suggestion--were not even mentioned. Everyone focused on the wrong
> thing (e.g. what would be a better name for "master").

There is another thread from the same time that contains quite a lot of
discussion on logistics. This subthread in particular raises the notion
of "let's try to minimize needing a special branch-name at all":

  https://lore.kernel.org/git/875zbrcpgh.fsf@evledraar.gmail.com/

And indeed, it led to some other bug-fixes in improvements in the time
since then:

  - submodule--helper was fixed to use HEAD from the remote as its
    fallback rather than a hard-coded "master"

  - fast-export --anonymize no longer treats "master" as special, but
    instead grew a flexible system for leaving some bits intact

  - fmt-merge-msg gained new options for configuring when it will print
    "into <branch>"

So really all that is left is deciding what to do when:

  git init
  git commit -m foo

is run. Obviously we added a config variable here, but we still fall
back to a hard-coded name. One suggestion was to not use any name, and
either require "git checkout -b some-branch" first, or commit onto a
detached HEAD:

  https://lore.kernel.org/git/B4814F42-7AF8-4D80-93D4-FAF752C72F21@me.com/

The simplicity has some appeal to me, but it's even less
backwards-compatible than falling back to a new different name.

I think Eric's suggestion of using the directory name as a default was
not previously mentioned. I'm not sure I would like that myself (I find
value in having a consistent "this is the main branch" name across
different repositories, at least for my workflows). And it creates all
of the same "every tutorial is now out of date" issues. But it is
neutral. I wouldn't be opposed to seeing it as a configurable option.

-Peff
Junio C Hamano Nov. 18, 2020, 12:07 a.m. UTC | #14
Jeff King <peff@peff.net> writes:

> I think Eric's suggestion of using the directory name as a default was
> not previously mentioned. I'm not sure I would like that myself (I find
> value in having a consistent "this is the main branch" name across
> different repositories, at least for my workflows). And it creates all
> of the same "every tutorial is now out of date" issues. But it is
> neutral. I wouldn't be opposed to seeing it as a configurable option.

I actually recall hearing it from Eric, not on this list, directly
back in the timeframe of these previous dicsussions.  I somehow
thought I relayed it to the community, perhaps #git-devel on
freenode, but apparently not to this list.

Yes, init.defaultBranchName is defined to be a string, so it is a
bit tricky to introduce special values that mean "no, not a
hardcoded value but derive dynamically based on X".  Perhaps use a
prefix that is not allowed in a refname, perhaps like this update to
the function that uses the value read from the init.defaultBranch
configuration variable.

 refs.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git c/refs.c w/refs.c
index 392f0bbf68..3fbc697cd8 100644
--- c/refs.c
+++ w/refs.c
@@ -576,6 +576,12 @@ char *repo_default_branch_name(struct repository *r)
 
 	if (!ret)
 		ret = xstrdup("master");
+	else if (!strcmp(ret, ":dirname"))
+		ret = ... do the $(basename $(cwd)) thing ...;
+	else if (!strcmp(ret, ":some other magic"))
+		ret = ... do some other magic thing ...;
+	else if (ret[0] == ':')
+		die(_("%s - unrecognised magic", ret);
 
 	full_ref = xstrfmt("refs/heads/%s", ret);
 	if (check_refname_format(full_ref, 0))
Junio C Hamano Nov. 18, 2020, 12:10 a.m. UTC | #15
Felipe Contreras <felipe.contreras@gmail.com> writes:

> If we already know "origin/HEAD" is very likely pointing to the
> integration branch, then why do we need to know what that branch is
> called in that particular project?
>
> Just refer to that branch as "origin/@", or just "origin".

"git merge origin" turns into "git merge origin/HEAD", I think, and
we had it for quite some time.

But repositories may not even have any origin to begin with.  The
one I am typing this message in certainly does not.  And we need
some fallback default when origin/HEAD cannot be used anyway, and
that is where the convention comes in again.  You cannot escape from
it, and ...

> That would work for projects that follow the convention, and those who
> don't. Why does the tool need to care?

... certainly it would not work for me.
Felipe Contreras Nov. 18, 2020, 12:18 a.m. UTC | #16
On Tue, Nov 17, 2020 at 5:33 PM Jeff King <peff@peff.net> wrote:
> On Tue, Nov 17, 2020 at 04:47:56PM -0600, Felipe Contreras wrote:

> > This should be easy to do if we make "origin" be a pseudo ref that
> > points to "origin/HEAD" (and we could introduce "origin/@").
>
> Didn't we already do this long ago? refs/remotes/%s/HEAD is special in
> the dwim_ref() lookup:
>
>   $ git rev-parse --symbolic-full-name origin
>   refs/remotes/origin/master

Hmmm. For some reason none of my remotes do have a HEAD.

If I do "git remote add", and then fetch, the HEAD doesn't seem to be present.
Felipe Contreras Nov. 18, 2020, 12:51 a.m. UTC | #17
On Tue, Nov 17, 2020 at 6:10 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> Felipe Contreras <felipe.contreras@gmail.com> writes:
>
> > If we already know "origin/HEAD" is very likely pointing to the
> > integration branch, then why do we need to know what that branch is
> > called in that particular project?
> >
> > Just refer to that branch as "origin/@", or just "origin".
>
> "git merge origin" turns into "git merge origin/HEAD", I think, and
> we had it for quite some time.
>
> But repositories may not even have any origin to begin with.  The
> one I am typing this message in certainly does not.  And we need
> some fallback default when origin/HEAD cannot be used anyway, and
> that is where the convention comes in again.  You cannot escape from
> it, and ...

I did not say the convention can be escaped, I said the convention can
be minimized.

Since apparently there's already support for "origin/HEAD", a lot of
documentation can avoid the term "origin/master", and simply use
"origin".

However, we need to make sure users have a properly set up
"origin/HEAD", and at least in my case none of my remotes have set it
up. Looking at the code, it seems:

  git clone URL test

Is different than:

  git init test
  git remote add origin URL
  git fetch origin
  git checkout -b $favorite origin

In the latter there is no origin/HEAD, and I don't see why that should
be the case.

Cheers.
Jeff King Nov. 18, 2020, 1:22 a.m. UTC | #18
On Tue, Nov 17, 2020 at 06:18:03PM -0600, Felipe Contreras wrote:

> On Tue, Nov 17, 2020 at 5:33 PM Jeff King <peff@peff.net> wrote:
> > On Tue, Nov 17, 2020 at 04:47:56PM -0600, Felipe Contreras wrote:
> 
> > > This should be easy to do if we make "origin" be a pseudo ref that
> > > points to "origin/HEAD" (and we could introduce "origin/@").
> >
> > Didn't we already do this long ago? refs/remotes/%s/HEAD is special in
> > the dwim_ref() lookup:
> >
> >   $ git rev-parse --symbolic-full-name origin
> >   refs/remotes/origin/master
> 
> Hmmm. For some reason none of my remotes do have a HEAD.
> 
> If I do "git remote add", and then fetch, the HEAD doesn't seem to be present.

Yes, I have run into that, and it's definitely annoying. The
refs/remotes/<remote>/HEAD symref is created by clone, but is not
updated by "fetch". That's intentional, because it's supposed to
represent a local choice (that is merely seeded by the remote side). But
it seems like adding it if it's missing might be reasonable.

I'm not sure if "git remote add" should be doing it (it already can do
it with "git remote set-head -a", but that is not the default when
adding a new remote, which otherwise does not contact the network at
all). Or if "git fetch" should be doing it. Certainly having "fetch
--update-remote-head" would be fine, but that doesn't really solve the
problem (which is that people don't realize they need to specify it).

There was some related discussion in:

  https://lore.kernel.org/git/CAEXP2g8-reK+u2FaO=mMP-nsvuDDWGpwV_tyKG5L5XpU=1LQeg@mail.gmail.com/

but I don't think any patches came out of that.

-Peff
Jeff King Nov. 18, 2020, 1:25 a.m. UTC | #19
On Tue, Nov 17, 2020 at 04:07:28PM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > I think Eric's suggestion of using the directory name as a default was
> > not previously mentioned. I'm not sure I would like that myself (I find
> > value in having a consistent "this is the main branch" name across
> > different repositories, at least for my workflows). And it creates all
> > of the same "every tutorial is now out of date" issues. But it is
> > neutral. I wouldn't be opposed to seeing it as a configurable option.
> 
> I actually recall hearing it from Eric, not on this list, directly
> back in the timeframe of these previous dicsussions.  I somehow
> thought I relayed it to the community, perhaps #git-devel on
> freenode, but apparently not to this list.

Could be. I don't keep up with the irc logs.

> Yes, init.defaultBranchName is defined to be a string, so it is a
> bit tricky to introduce special values that mean "no, not a
> hardcoded value but derive dynamically based on X".  Perhaps use a
> prefix that is not allowed in a refname, perhaps like this update to
> the function that uses the value read from the init.defaultBranch
> configuration variable.

Yeah, I restrained myself from getting too far into thinking about
syntax, but I agree we'd want something like that. It might also be OK
to use something that's extremely unlikely to be a default branch name
(like BASENAME), but the ":" syntax you have here isn't bad. Yet another
option is a separate variable (that if set means we do not look at
init.defaultBranch at all).

IMHO, though, all of this is orthogonal to question of what the default
is. Unless we are thinking the basename thing would work as a default,
but I don't think that resolves any of the backwards-compatibility
concerns.

-Peff
Felipe Contreras Nov. 18, 2020, 1:45 a.m. UTC | #20
On Tue, Nov 17, 2020 at 7:22 PM Jeff King <peff@peff.net> wrote:
>
> On Tue, Nov 17, 2020 at 06:18:03PM -0600, Felipe Contreras wrote:
>
> > On Tue, Nov 17, 2020 at 5:33 PM Jeff King <peff@peff.net> wrote:
> > > On Tue, Nov 17, 2020 at 04:47:56PM -0600, Felipe Contreras wrote:
> >
> > > > This should be easy to do if we make "origin" be a pseudo ref that
> > > > points to "origin/HEAD" (and we could introduce "origin/@").
> > >
> > > Didn't we already do this long ago? refs/remotes/%s/HEAD is special in
> > > the dwim_ref() lookup:
> > >
> > >   $ git rev-parse --symbolic-full-name origin
> > >   refs/remotes/origin/master
> >
> > Hmmm. For some reason none of my remotes do have a HEAD.
> >
> > If I do "git remote add", and then fetch, the HEAD doesn't seem to be present.
>
> Yes, I have run into that, and it's definitely annoying. The
> refs/remotes/<remote>/HEAD symref is created by clone, but is not
> updated by "fetch". That's intentional, because it's supposed to
> represent a local choice (that is merely seeded by the remote side). But
> it seems like adding it if it's missing might be reasonable.

The equivalent of this choice is in "git remote add -m":

  With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD`
  is set up to point at remote's `<master>` branch. See also the
  set-head command.

This is of course inconsistent. Is it the "head", or is it the "master"?

Presumably if we want to avoid the term "master", then this option
needs to be renamed.

In my opinion unless this option has been explicitly set,
"origin/HEAD" should keep track of whatever remote head is set.

If somebody updates its remote HEAD from "master" to "main", then
origin/HEAD should be updated accordingly. Granted, this may be some
overhead in the 99.999% of the cases where the remote HEAD is the
same, so it may not be worth even thinking about it.

But at least the first fetch after "git remote add" should fetch it,
in my opinion (unless it's manually configured already). I'm not sure
if origin/HEAD can contain some placeholder so that "git fetch" knows
what to do.

Cheers.
Jeff King Nov. 18, 2020, 2:06 a.m. UTC | #21
On Tue, Nov 17, 2020 at 07:45:21PM -0600, Felipe Contreras wrote:

> > Yes, I have run into that, and it's definitely annoying. The
> > refs/remotes/<remote>/HEAD symref is created by clone, but is not
> > updated by "fetch". That's intentional, because it's supposed to
> > represent a local choice (that is merely seeded by the remote side). But
> > it seems like adding it if it's missing might be reasonable.
> 
> The equivalent of this choice is in "git remote add -m":
> 
>   With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD`
>   is set up to point at remote's `<master>` branch. See also the
>   set-head command.

Wow, I'm not sure how that option escaped my notice for all these years.
Of course it would be much more useful if it pulled the value from the
remote HEAD (but again, unless we use "-f" we are not contacting the
remote at all).

> This is of course inconsistent. Is it the "head", or is it the "master"?
> 
> Presumably if we want to avoid the term "master", then this option
> needs to be renamed.

Agreed that the naming is bad.

> In my opinion unless this option has been explicitly set,
> "origin/HEAD" should keep track of whatever remote head is set.
> 
> If somebody updates its remote HEAD from "master" to "main", then
> origin/HEAD should be updated accordingly. Granted, this may be some
> overhead in the 99.999% of the cases where the remote HEAD is the
> same, so it may not be worth even thinking about it.
> 
> But at least the first fetch after "git remote add" should fetch it,
> in my opinion (unless it's manually configured already). I'm not sure
> if origin/HEAD can contain some placeholder so that "git fetch" knows
> what to do.

If it's simply not present (which is the case now after "git remote
add"), then it might be reasonable for "git fetch" to use that as the
hint to fill it in. That would also make "git remote add -f" just work,
I believe.

It does mean that you can _change_ the value of origin/HEAD, but you
wouldn't be allowed to delete it without fetch trying to re-create it.
I suspect this is quite rare, but we might want an escape hatch config.
E.g., remote.origin.updateHEAD that can be set to one of:

  - never; do not touch it

  - create-if-missing; as discussed here

  - always; update it on every fetch

And then it is just a question of what the default is. Currently it is
"never". I suspect most people would be happy with "always", but it does
break some existing flows. But perhaps "create-if-missing" is a good
medium.

-Peff
Jonathan Nieder Nov. 18, 2020, 2:39 a.m. UTC | #22
Hi,

Jeff King wrote:
> On Tue, Nov 17, 2020 at 07:45:21PM -0600, Felipe Contreras wrote:
>> Jeff King wrote:

>>> Yes, I have run into that, and it's definitely annoying. The
>>> refs/remotes/<remote>/HEAD symref is created by clone, but is not
>>> updated by "fetch". That's intentional, because it's supposed to
>>> represent a local choice (that is merely seeded by the remote side). But
>>> it seems like adding it if it's missing might be reasonable.
>>
>> The equivalent of this choice is in "git remote add -m":
>>
>>   With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD`
>>   is set up to point at remote's `<master>` branch. See also the
>>   set-head command.
>
> Wow, I'm not sure how that option escaped my notice for all these years.
> Of course it would be much more useful if it pulled the value from the
> remote HEAD (but again, unless we use "-f" we are not contacting the
> remote at all).

When would I want this implicit "set-head -a" and *not* want "-f"?

[...]
>> Presumably if we want to avoid the term "master", then this option
>> needs to be renamed.
>
> Agreed that the naming is bad.

That said, single-letter options often have bad names.  (That's part of
why these days I try to push back against single-letter options unless
a flag is frequently used.)

For consistency with "git clone -b", I suppose one might expect it to
be "git remote add -b".  Or even better, to retire the option and have
people run "git remote set-head" separately.

[...]
> E.g., remote.origin.updateHEAD that can be set to one of:
>
>   - never; do not touch it
>
>   - create-if-missing; as discussed here
>
>   - always; update it on every fetch
>
> And then it is just a question of what the default is. Currently it is
> "never". I suspect most people would be happy with "always", but it does
> break some existing flows. But perhaps "create-if-missing" is a good
> medium.

Thanks for bringing this up --- this is something I had been
interested in as well but hadn't gotten around to contacting the list
about it.

The default value for a config setting like this has two purposes:

- it makes the config setting for affected people who have not
  discovered it

- it provides a sensible, predictable standard behavior

Those two goals are often in tension, as they were for example when
setting the default for push.default.

If I consider them separately:

- to make as smooth a transition as possible for people who were
  relying on "git remote set-head", a good behavior would be to
  *fail the fetch* when the remote HEAD changes.  That would force
  the user to make a choice between "never" and "always".

- one way to relax that without hurting that goal too much would be to
  fail the fetch when the remote HEAD changes from something other
  than "master" or "main".  That way, the common case (moving from a
  default to a project-appropriate setting) would work without
  friction, and in other cases the user could make a choice between
  "never" and "always".

- all that said, the default that I prefer is simply "always".  Like
  Felipe hinted, this is a simple, intuitive behavior that most people
  would expect.

As a transition plan, I can imagine going from one of those first two
to the third after some appropriate period of time has passed.

What do you think?

Thanks,
Jonathan
Jonathan Nieder Nov. 18, 2020, 2:40 a.m. UTC | #23
Jeff King wrote:

> IMHO, though, all of this is orthogonal to question of what the default
> is. Unless we are thinking the basename thing would work as a default,
> but I don't think that resolves any of the backwards-compatibility
> concerns.

If we think it would make sense as the *eventual* default, we could use

	[init]
		defaultBranchName =

(i.e., an empty string) to request it early.
Jonathan Nieder Nov. 18, 2020, 2:56 a.m. UTC | #24
Eric W. Biederman wrote:

> Instead of having a fixed name across all repos for the initially
> created branch can we instead use the directory name of the repo for the
> branch name?
>
> Advantages:
>
> - The branch name that is somewhat meaningful to the creator of the git
>   repo.
>
>   I have at least two repos where I wound up doing this by hand.  So at
>   least for me it is something I am doing anyway.

Example: this would make the main branch in a new git.git repository
default to "git".  However, we would be free to switch to some other
workflow-specific name like "stable".

> - Tools can not hard code the name of an initially created branch and
>   expect it to work.
>
>   This moves us farther from the realm of people assuming incorrectly
>   that there is something special about the branch created by default.

What's especially nice about this is that a repository's local
basename and the URL at which it gets published do not always
coincide.  So scripts designed to be robust would be more likely to
use commands like "git branch --show-current" instead of trying to
guess using the new rule.

That said, if I put myself in the shoes of such a script author for a
moment, I'm likely to be irritated.  What started as a static string
now becomes something dynamic.  If I put myself in the shoes of
someone who has *inherited* a script (a testsuite, maybe), I'm likely
to be even more irritated.

For testsuites, one can buy time by setting init.defaultBranch, but
not for other scripts.

Are there things we can do to make a script author's life easier?

Today if I want to look up a remote repository's default branch,
the best I can do is

	git ls-remote --symref origin HEAD

The output is not as easy to parse as I'd like: it's split between two
lines and has multiple fields on each line.  Worse, it is slow, since
it scans all refs instead of just the ref I wanted.  Even worse, if
another ref in the remote repository ends with /HEAD (e.g.,
refs/remotes/someremote/HEAD), it prints that, too.

If I could do something like

	git ls-remote --format='%(symref)' --exact-match origin HEAD

(using for-each-ref style formats, and allowing exact matching) then
that would be helpful.

In general, this aspect of a less deterministic first branchname is
appealing; it would result in improving the quality of the ecosystem
of tools built around Git.  This is what I like most about this
proposal.

[...]
> At least for my usage main is a pretty huge misnomer as I barely use the
> branch with the master.  Renaming my unused branch main implies that I
> am using the tool wrong.

Is that because "master" is inherited from your upstream?  Which
branch would you want people to check out by default when they clone
from your repo?

For what it's worth:

- I find this proposal really tempting, and have liked it since the
  moment gitster brought it up on #git-devel.  The main reason I
  haven't brought it up since then is that I didn't have a patch
  implementing it. :)

- That said, a fixed string as default would be fine with me, too.

Thanks,
Jonathan
Junio C Hamano Nov. 18, 2020, 5:43 a.m. UTC | #25
Jonathan Nieder <jrnieder@gmail.com> writes:

>> IMHO, though, all of this is orthogonal to question of what the default
>> is. Unless we are thinking the basename thing would work as a default,
>> but I don't think that resolves any of the backwards-compatibility
>> concerns.
>
> If we think it would make sense as the *eventual* default, we could use
>
> 	[init]
> 		defaultBranchName =
>
> (i.e., an empty string) to request it early.

I am not opposed to the idea to invent a notation that asks for the
basename behaviour, but I do not think it is a good idea to use "an
empty string" for that.  I'd rather see us use some consistent
naming convention to denote any new "non-constant string" thing.

What Peff suggested is a more viable possibility, for example.  When
"[init] defaultBranchAlgorithm = <name>" is set, the fixed string
"init.defaultBranch" is ignored and the algorithm specified with its
name is invoked to come up with a name dynamically.  We may start
with something like 'dirname' as the only supported algorithm but
that way we would avoid painting ourselves in a corner out of which
we cannot escape (e.g. we may come up with a better way than the
basename thing, and we would not have a good way to give it a name
that is easy to use if we wasted "an empty string" for the basename
thing).
Junio C Hamano Nov. 18, 2020, 5:57 a.m. UTC | #26
Jonathan Nieder <jrnieder@gmail.com> writes:

> That said, if I put myself in the shoes of such a script author for a
> moment, I'm likely to be irritated.  What started as a static string
> now becomes something dynamic.  If I put myself in the shoes of
> someone who has *inherited* a script (a testsuite, maybe), I'm likely
> to be even more irritated.

It is conceptually really nice to say that we do not use words like
'master' and 'main' that are 'meaningless' in the context of
thinking about the workflow used for the project and instead pick
the word the end user chose to call (some aspect of) the project
(i.e. the name of the directory to host its working tree).  It
however is much harder to defend the design in real life because it
can lead to the irritations you mention.

> Are there things we can do to make a script author's life easier?

It largely depends on what "specialness" of 'master' branch the
script is interested in, isn't it?

> Today if I want to look up a remote repository's default branch,
> the best I can do is
>
> 	git ls-remote --symref origin HEAD
>
> The output is not as easy to parse as I'd like:...

In a sense, these follower repositories are easier to work with.

You have refs/remotes/origin/HEAD that indicates what the owner of
the local repository considers of the most significance; it is
initialized to match what the remote had pointed with its HEAD when
the repository was cloned, but the local user can repoint it when
the local interest diverge from that of the remote's.  And you do
not need to talk over the network with ls-remote to find that
out (actually asking ls-remote may actively be wrong after the
local user repointed it); you only need to ask 'git symbolic-ref'
which is totally local.
Felipe Contreras Nov. 18, 2020, 9:04 a.m. UTC | #27
On Tue, Nov 17, 2020 at 8:06 PM Jeff King <peff@peff.net> wrote:
> On Tue, Nov 17, 2020 at 07:45:21PM -0600, Felipe Contreras wrote:

> > The equivalent of this choice is in "git remote add -m":
> >
> >   With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD`
> >   is set up to point at remote's `<master>` branch. See also the
> >   set-head command.
>
> Wow, I'm not sure how that option escaped my notice for all these years.
> Of course it would be much more useful if it pulled the value from the
> remote HEAD (but again, unless we use "-f" we are not contacting the
> remote at all).

Seems to come basically untouched since 2007:

  b6f5da1e0f (Teach git-remote add to fetch and track)

> And then it is just a question of what the default is. Currently it is
> "never". I suspect most people would be happy with "always", but it does
> break some existing flows. But perhaps "create-if-missing" is a good
> medium.

Agreed. Personally I don't see any problem with "create-if-missing",
but creating a configuration and defaulting to "never" should be a
good first step.

I'm sending an RFC patch to that effect.

Cheers.
Felipe Contreras Nov. 18, 2020, 10:12 a.m. UTC | #28
On Tue, Nov 17, 2020 at 8:39 PM Jonathan Nieder <jrnieder@gmail.com> wrote:
> Jeff King wrote:
> > On Tue, Nov 17, 2020 at 07:45:21PM -0600, Felipe Contreras wrote:
> >> Jeff King wrote:
>
> >>> Yes, I have run into that, and it's definitely annoying. The
> >>> refs/remotes/<remote>/HEAD symref is created by clone, but is not
> >>> updated by "fetch". That's intentional, because it's supposed to
> >>> represent a local choice (that is merely seeded by the remote side). But
> >>> it seems like adding it if it's missing might be reasonable.
> >>
> >> The equivalent of this choice is in "git remote add -m":
> >>
> >>   With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD`
> >>   is set up to point at remote's `<master>` branch. See also the
> >>   set-head command.
> >
> > Wow, I'm not sure how that option escaped my notice for all these years.
> > Of course it would be much more useful if it pulled the value from the
> > remote HEAD (but again, unless we use "-f" we are not contacting the
> > remote at all).
>
> When would I want this implicit "set-head -a" and *not* want "-f"?

This is what I often do:

 git remote add origin $url
 git fetch origin

That should work (update origin/HEAD), and it currently doesn't.

> > E.g., remote.origin.updateHEAD that can be set to one of:
> >
> >   - never; do not touch it
> >
> >   - create-if-missing; as discussed here
> >
> >   - always; update it on every fetch
> >
> > And then it is just a question of what the default is. Currently it is
> > "never". I suspect most people would be happy with "always", but it does
> > break some existing flows. But perhaps "create-if-missing" is a good
> > medium.
>
> Thanks for bringing this up --- this is something I had been
> interested in as well but hadn't gotten around to contacting the list
> about it.
>
> The default value for a config setting like this has two purposes:
>
> - it makes the config setting for affected people who have not
>   discovered it
>
> - it provides a sensible, predictable standard behavior
>
> Those two goals are often in tension, as they were for example when
> setting the default for push.default.
>
> If I consider them separately:
>
> - to make as smooth a transition as possible for people who were
>   relying on "git remote set-head", a good behavior would be to
>   *fail the fetch* when the remote HEAD changes.  That would force
>   the user to make a choice between "never" and "always".

We don't need to fail the fetch, we can print a warning so the user
can decide what to do next, including ignoring the warning.

Moreover, since projects rarely change the HEAD, we might want to
print the warning always, until the user sets the configuration.

> - one way to relax that without hurting that goal too much would be to
>   fail the fetch when the remote HEAD changes from something other
>   than "master" or "main".  That way, the common case (moving from a
>   default to a project-appropriate setting) would work without
>   friction, and in other cases the user could make a choice between
>   "never" and "always".

This thread started in an attempt to move away from hard-coded values.
This doesn't help in my opinion.

> - all that said, the default that I prefer is simply "always".  Like
>   Felipe hinted, this is a simple, intuitive behavior that most people
>   would expect.
>
> As a transition plan, I can imagine going from one of those first two
> to the third after some appropriate period of time has passed.

I think the default should be "missing", after a warning period. And
perhaps change it to "always" in the next major version, but that
basically gets rid of the manual "origin/HEAD" that seems to have been
there since forever (at least 2007).

I personally don't see any point in manually setting the HEAD (I have
never done so), but that's just me, others might.

Cheers.
Johannes Schindelin Nov. 18, 2020, 11:32 a.m. UTC | #29
Hi Junio,

On Tue, 17 Nov 2020, Junio C Hamano wrote:

> Jonathan Nieder <jrnieder@gmail.com> writes:
>
> >> IMHO, though, all of this is orthogonal to question of what the default
> >> is. Unless we are thinking the basename thing would work as a default,
> >> but I don't think that resolves any of the backwards-compatibility
> >> concerns.
> >
> > If we think it would make sense as the *eventual* default, we could use
> >
> > 	[init]
> > 		defaultBranchName =
> >
> > (i.e., an empty string) to request it early.
>
> I am not opposed to the idea to invent a notation that asks for the
> basename behaviour, but I do not think it is a good idea to use "an
> empty string" for that.  I'd rather see us use some consistent
> naming convention to denote any new "non-constant string" thing.

At least in the tests, using the empty string for
`GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME` is equivalent for not setting it at
all, i.e. to trigger the fall-back.

So yes, I totally agree that triggering an interactive prompt by the empty
value is not really a good idea (nor a particularly intuitive behavior).

With your idea to special-case any value starting with a colon, `:ask:`
seems like a saner approach.

Having said that, I would still favor the fall-back `main` over this idea:
it is a much smaller (and less annoying) change of behavior to use a less
loaded name than to change from a previously non-interactive to a
now-interactive operation.

As to using the base name by default: I don't think that is a good idea at
all. Not only doesn't it work when you run `git init` in the root
directory (which some people do, and that's totally okay with me), it also
does not work with any base name that isn't a valid ref name. Try this at
home:

	$ git check-ref-format --branch "My Documents"
	fatal: 'My Documents' is not a valid branch name

So while it is a cute idea, in general it will simply fail, and is
therefore worse than any alternative that does _not_ fail in general.

> What Peff suggested is a more viable possibility, for example.  When
> "[init] defaultBranchAlgorithm = <name>" is set, the fixed string
> "init.defaultBranch" is ignored and the algorithm specified with its
> name is invoked to come up with a name dynamically.  We may start
> with something like 'dirname' as the only supported algorithm but
> that way we would avoid painting ourselves in a corner out of which
> we cannot escape (e.g. we may come up with a better way than the
> basename thing, and we would not have a good way to give it a name
> that is easy to use if we wasted "an empty string" for the basename
> thing).

Indeed. In the spirit of minimizing disruption (as promised in
https://sfconservancy.org/news/2020/jun/23/gitbranchname/), I would like
to stay away from changing the default behavior _that_ much.

My current plan is to implement a warning in `git init` (much like the
`pull.rebase` one, which I thought would raise outcries of frustration,
but to my surprise this did not happen, and `git init` is _a lot_ less
common than `git pull`).

This needs to be done with care, obviously. I haven't looked yet, but I
think there is a chance that `git clone` would implicitly look at
`init.defaultBranch` only to override it later by the name of the remote
primary branch. In that case, we obviously do not want to warn the user
because the `init.defaultBranch` value is not actually used.

Ciao,
Dscho
Junio C Hamano Nov. 18, 2020, 3:43 p.m. UTC | #30
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> So yes, I totally agree that triggering an interactive prompt by the empty
> value is not really a good idea (nor a particularly intuitive behavior).

Puzzled.

Nobody talked about going interactive so far and I didn't suggest
it---even though I think it is a cute idea to give a "what branch
name do you want to use?" prompt, I do not think it is practical.

I thought it was obvious, but the key to coming up with a name
dynamically instead of using a fixed string is to derive from a cue
the end user gives, not directly use what the end user gives.  I do
not think anybody in the discussion meant by "the <basename> thing"
to literally use $(basename $(cwd)) output, but use it to derive a
token that check-ref-format likes.  As you may have already known
when you wrote them, "My Documents" or the root directory case are
red herring---it would be trivial to derive "MyDocuments" or
"my-documents" for the former, and for the latter, it is totally OK
for the deriving rule to come up with any of "unnamed", "initial",
etc.

Most of the thing you said in the message I am responding to did not
make much sense to me.  Perhaps you can retry after reading the
message you are responding to again?

Thanks.
Johannes Schindelin Nov. 18, 2020, 8:58 p.m. UTC | #31
Hi Junio,

On Tue, 17 Nov 2020, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > 	case "$TEST_NUMBER" in
> > 	3404|4013|5310|5526|6300|7064|7817|9902)
> > 		# Avoid conflicts with patch series that are cooking at the same
> > 		# time
> > 		# as the patch series changing the default of
> > 		# `init.defaultBranch`.
> > 		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
> > 		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> > 		;;
> > 	*)
> > 		GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> > 		export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> > 		;;
> > 	esac
>
> I actually am not a big fan of the centralized table of "these want
> to run with main".  My ideal would be to have an explicit assignment
> of either master or main for tests that absolutely require the
> default to be one of these names at the top of these script, and any
> test scripts that do not care what the initial branch is called
> (perhaps because they begin by switching to a branch whose name is
> picked by them immediately after they start and use that name
> throughout) won't have GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME in them.

I will make it so in v3.

It does make sense, too: the four patch series I sent out in the past
hours address some issues that I would have otherwise missed in the
transition (in particular, two test cases with `test_must_fail` in them
would have continued to pass, but for the wrong reason, during the
transition to `main`.

Ciao,
Dscho
Philip Oakley Nov. 18, 2020, 11:45 p.m. UTC | #32
On 17/11/2020 22:55, Junio C Hamano wrote:
>  I personally
> do not like the word 'main' used as such, but the rest of the world
> seems to be moving in that direction,

I feel that 'main' is rather a rather dull and boring sort of word.

In that sense, it could be useful as the fall back for those who haven't
yet got a clear view of what they want to call their first born. So I
sort of support both views.

An alternative in the other direction is to go with the 'not currently
on any branch' (detached at nowhere) but then require users to
deliberately create their first branch with their chosen name. This
moves the 'backward incompatibility' to a different place, which may be
easier to manage.
--
Philip
Johannes Schindelin Nov. 19, 2020, midnight UTC | #33
Hi Philip,

On Wed, 18 Nov 2020, Philip Oakley wrote:

> An alternative in the other direction is to go with the 'not currently
> on any branch' (detached at nowhere) but then require users to
> deliberately create their first branch with their chosen name. This
> moves the 'backward incompatibility' to a different place, which may be
> easier to manage.

It might be easier to manage for _us_, the Git developers. But every user
who initializes a repository and wants to push now needs to take the extra
step to give their unnamed branch ("detached HEAD" is _still_ confusing
new users!!!) a name.

That would be much more disruptive than choosing a "rather dull and
boring" name instead of a rather racially-charged one.

And we promised to try to minimize the disruption to Git users.

Ciao,
Dscho
Philip Oakley Nov. 19, 2020, 12:30 a.m. UTC | #34
Hi Dscho,

On 19/11/2020 00:00, Johannes Schindelin wrote:
> Hi Philip,
>
> On Wed, 18 Nov 2020, Philip Oakley wrote:
>
>> An alternative in the other direction is to go with the 'not currently
>> on any branch' (detached at nowhere) but then require users to
>> deliberately create their first branch with their chosen name. This
>> moves the 'backward incompatibility' to a different place, which may be
>> easier to manage.
> It might be easier to manage for _us_, the Git developers. But every user
> who initializes a repository and wants to push now

Is this 'emerges fully formed' initialise & push  really that common.

I'd be expecting a few add & commits prior to the push, so plenty of
time for deciding and creating the chosen branch. At least that was the
thought process...

>  needs to take the extra
> step to give their unnamed branch

>  ("detached HEAD" is _still_ confusing
> new users!!!) a name.
I'd only mentioned the detached head to keep the devs happy ;-) I'm
quite happy with a "not on any named branch yet" type message for normal
usage.

>
> That would be much more disruptive than choosing a "rather dull and
> boring" name instead of a rather racially-charged one.
"Main" is fine, but Junio had mention say "Primary" as being more
positive, but that is begging the question for the user. We should let
them chose.

Hence using the not greatly inspiring 'main' as a starter offering would
match that desire that the user should, ideally, make their own choice. 
>
> And we promised to try to minimize the disruption to Git users.
...but we haven't said 'it' is an ignorable issue. There's still a lot
of old documentation and inertia to overcome.
>
> Ciao,
> Dscho
Philip
Peter Hadlaw Nov. 19, 2020, 12:30 a.m. UTC | #35
Hello,

It's worth noting that the word "slave" comes from the en_slav_ement
of Slavs (the Slavic people of Eastern Europe).

I encourage the whole git team to really think about the changes you are making.

It was just reported to me that a professional friend of mine had
confusion as to why,
after initializing a new repository, they couldn't navigate to the
`master` branch of their repository.

I understand this is back-of-the-napkin type math but stay with me for
one moment.
I also understand GitHub is not all of git users, but I just pulled
the number to help me out here.

If GitHub has 40 million users but let's say half of them aren't
active, so now we are at 20 million.
(Replace this number with how many actual users of git are out there.)

Let's even say half of them are on board and aware of this "harmless"
change to a more "sensitive" doublespeak representation of the
"master" copy/branch of the repo.

That leaves us with 10 million users of git that are either unaware or
are not on board. Let's say it takes 3 minutes for a user to search on
the web why exactly they can't
navigate to their "master" branch. That's 30 million minutes of time
wasted, or about 57 man-YEARs of time wasted.... for what?

When do we put our foot down and say enough is enough, and not
everything is offensive?

Again, please reconsider making this change towards doublespeak and
consider the ramifications of how much actual human life & time will
be wasted.

Kind Regards,
Peter

On Wed, Nov 18, 2020 at 6:01 PM Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
>
> Hi Philip,
>
> On Wed, 18 Nov 2020, Philip Oakley wrote:
>
> > An alternative in the other direction is to go with the 'not currently
> > on any branch' (detached at nowhere) but then require users to
> > deliberately create their first branch with their chosen name. This
> > moves the 'backward incompatibility' to a different place, which may be
> > easier to manage.
>
> It might be easier to manage for _us_, the Git developers. But every user
> who initializes a repository and wants to push now needs to take the extra
> step to give their unnamed branch ("detached HEAD" is _still_ confusing
> new users!!!) a name.
>
> That would be much more disruptive than choosing a "rather dull and
> boring" name instead of a rather racially-charged one.
>
> And we promised to try to minimize the disruption to Git users.
>
> Ciao,
> Dscho
Philip Oakley Nov. 19, 2020, 12:44 a.m. UTC | #36
On 19/11/2020 00:30, Peter Hadlaw wrote:
> That leaves us with 10 million users of git that are either unaware or
> are not on board. Let's say it takes 3 minutes for a user to search on
> the web why exactly they can't
> navigate to their "master" branch. That's 30 million minutes of time
> wasted, or about 57 man-YEARs of time wasted.... for what?
That's (3 mins) probably about the same amount of time as most users
waste on stack overflow for Git questions, or the old 'RTFM', for their
problems in a typical week anyway.

3 mins out of a 35 hr week, over a 44 week x 25 year life is 1.3 ppm,
unless you work too hard and too long, where it's an even lower ppm.

There are mechanism in this series for setting the default branch name.

--
Philip
Peter Hadlaw Nov. 19, 2020, 12:55 a.m. UTC | #37
There's still a responsibility for ~57 years worth of human life that
doesn't actually need to be put at risk.

Someone forgetting how to rebase a branch in some given way and then
having to search is their own responsibility.
On the other hand, this is a decision made on their behalf, without
their consent, ... on everyone's behalf.

If you're not going to change the default without user input, are you
going to ask the user for a default branch name?
Figure out the math and annoyance on that.

On Wed, Nov 18, 2020 at 6:44 PM Philip Oakley <philipoakley@iee.email> wrote:
>
> On 19/11/2020 00:30, Peter Hadlaw wrote:
> > That leaves us with 10 million users of git that are either unaware or
> > are not on board. Let's say it takes 3 minutes for a user to search on
> > the web why exactly they can't
> > navigate to their "master" branch. That's 30 million minutes of time
> > wasted, or about 57 man-YEARs of time wasted.... for what?
> That's (3 mins) probably about the same amount of time as most users
> waste on stack overflow for Git questions, or the old 'RTFM', for their
> problems in a typical week anyway.
>
> 3 mins out of a 35 hr week, over a 44 week x 25 year life is 1.3 ppm,
> unless you work too hard and too long, where it's an even lower ppm.
>
> There are mechanism in this series for setting the default branch name.
>
> --
> Philip
>
Junio C Hamano Nov. 19, 2020, 1:51 a.m. UTC | #38
Philip Oakley <philipoakley@iee.email> writes:

> An alternative in the other direction is to go with the 'not currently
> on any branch' (detached at nowhere) but then require users to
> deliberately create their first branch with their chosen name. This
> moves the 'backward incompatibility' to a different place, which may be
> easier to manage.

As has already been mentioned by Peff, I do not think that is a
workable alternative, especially given that people are generally
afraid of and easily get confused by being on a detached HEAD.

And there is no such thing as unborn detached HEAD.  Existing
versions of Git would not consider a $GIT_DIR that does not have any
HEAD, which means a new repository created by such an "initially
there is no branch" version of Git cannot be accessed by any
existing versions of Git.

It raises the backward incompatibility of such an approach to a
whole new level that is simply unmanageable, I am afraid.
Johannes Schindelin Nov. 19, 2020, 9:22 a.m. UTC | #39
Hi Junio,

On Wed, 18 Nov 2020, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > So yes, I totally agree that triggering an interactive prompt by the empty
> > value is not really a good idea (nor a particularly intuitive behavior).
>
> Puzzled.
>
> Nobody talked about going interactive so far and I didn't suggest
> it---even though I think it is a cute idea to give a "what branch
> name do you want to use?" prompt, I do not think it is practical.

The interactive prompt was what I understood your "a notation that asks
for the basename behaviour" comment. The "ask" was what tripped me up, I
always interpret that as interactive. But now that I re-read it, I
understand that you had not thought that far yet.

> I thought it was obvious, but the key to coming up with a name
> dynamically instead of using a fixed string is to derive from a cue
> the end user gives, not directly use what the end user gives.  I do
> not think anybody in the discussion meant by "the <basename> thing"
> to literally use $(basename $(cwd)) output, but use it to derive a
> token that check-ref-format likes.  As you may have already known
> when you wrote them, "My Documents" or the root directory case are
> red herring---it would be trivial to derive "MyDocuments" or
> "my-documents" for the former, and for the latter, it is totally OK
> for the deriving rule to come up with any of "unnamed", "initial",
> etc.

The more magic you introduce, the less intuitive the whole thing gets, and
the more disruptive the change.

> Most of the thing you said in the message I am responding to did not
> make much sense to me.  Perhaps you can retry after reading the
> message you are responding to again?

Could you be a bit more specific?

Was it the "I already use the empty string to force a fall-back, it cannot
also mean something else" that did not make sense?

Or my comment that special-casing values that start with a colon would
look saner to me?

Or the comment about the basename in a root directory?

Or referencing the SFC statement that we want to minimize disruption?

Or my stated preference to go with `main` in order to fulfill that promise
of minimizing the disruption to users?

Or my current plan to introduce an `advise()` call when running `git init`
that tells users that the fall-back for `init.defaultBranch` will change
soon and that users are encouraged to configure it if they care about
keeping the current fall-back?

Or that all of this needs to be done with care?

The message you refer to might not have been the best example of clear
communication, but it hardly deserved _that_ response.

Ciao,
Dscho
Philip Oakley Nov. 19, 2020, 10:35 a.m. UTC | #40
On 19/11/2020 01:51, Junio C Hamano wrote:
> Philip Oakley <philipoakley@iee.email> writes:
>
>> An alternative in the other direction is to go with the 'not currently
>> on any branch' (detached at nowhere) but then require users to
>> deliberately create their first branch with their chosen name. This
>> moves the 'backward incompatibility' to a different place, which may be
>> easier to manage.
> As has already been mentioned by Peff, I do not think that is a
> workable alternative, especially given that people are generally
> afraid of and easily get confused by being on a detached HEAD.
Yes, our use of the technical phrase 'detached HEAD' is confusing,
compared with the more pleasant 'not on any branch', or 'not at a branch
tip'. Such is the curse of knowledge.
>
> And there is no such thing as unborn detached HEAD.  Existing
> versions of Git would not consider a $GIT_DIR that does not have any
> HEAD, which means a new repository created by such an "initially
> there is no branch" version of Git cannot be accessed by any
> existing versions of Git.
Isn't this, essentially, because there is no 'empty/null commit' that we
(HEAD) could start at? There have been a few cases where I've been
'annoyed' that we're missing that. (rather than the orphan branch approach)
>
> It raises the backward incompatibility of such an approach to a
> whole new level that is simply unmanageable, I am afraid.
OK, accepted.

Philip
Sergey Organov Nov. 19, 2020, 11:10 a.m. UTC | #41
Philip Oakley <philipoakley@iee.email> writes:

> On 19/11/2020 01:51, Junio C Hamano wrote:
>> Philip Oakley <philipoakley@iee.email> writes:
>>
>>> An alternative in the other direction is to go with the 'not currently
>>> on any branch' (detached at nowhere) but then require users to
>>> deliberately create their first branch with their chosen name. This
>>> moves the 'backward incompatibility' to a different place, which may be
>>> easier to manage.
>> As has already been mentioned by Peff, I do not think that is a
>> workable alternative, especially given that people are generally
>> afraid of and easily get confused by being on a detached HEAD.
> Yes, our use of the technical phrase 'detached HEAD' is confusing,
> compared with the more pleasant 'not on any branch', or 'not at a branch
> tip'. Such is the curse of knowledge.

To me "not on a branch [tip]" is also confusing, as in fact you are, as
is easily seen after you perform a few commits, and now HEAD points
directly to the tip of the branch (that has no other references).

I wonder why Git didn't rather adopt "unnamed branch" or "nameless
branch" to describe this mode of operation?

-- Sergey
Philip Oakley Nov. 19, 2020, 11:50 a.m. UTC | #42
On 19/11/2020 11:10, Sergey Organov wrote:
> Philip Oakley <philipoakley@iee.email> writes:
>
>> On 19/11/2020 01:51, Junio C Hamano wrote:
>>> Philip Oakley <philipoakley@iee.email> writes:
>>>
>>>> An alternative in the other direction is to go with the 'not currently
>>>> on any branch' (detached at nowhere) but then require users to
>>>> deliberately create their first branch with their chosen name. This
>>>> moves the 'backward incompatibility' to a different place, which may be
>>>> easier to manage.
>>> As has already been mentioned by Peff, I do not think that is a
>>> workable alternative, especially given that people are generally
>>> afraid of and easily get confused by being on a detached HEAD.
>> Yes, our use of the technical phrase 'detached HEAD' is confusing,
>> compared with the more pleasant 'not on any branch', or 'not at a branch
>> tip'. Such is the curse of knowledge.
> To me "not on a branch [tip]" is also confusing, as in fact you are, as
> is easily seen after you perform a few commits, and now HEAD points
> directly to the tip of the branch (that has no other references).
>
> I wonder why Git didn't rather adopt "unnamed branch" or "nameless
> branch" to describe this mode of operation?
Given the ephemeral nature of branches they sound like good suggestion.

However I suspect "history" to be the "why" of the current 'detached
head' usage.
Maybe it's a side reference to Nearly Headless Nick or other discussions
of the time (aka lost in history)?
--
Philip
Sergey Organov Nov. 19, 2020, 12:33 p.m. UTC | #43
Philip Oakley <philipoakley@iee.email> writes:

> On 19/11/2020 11:10, Sergey Organov wrote:
>> Philip Oakley <philipoakley@iee.email> writes:
>>
>>> On 19/11/2020 01:51, Junio C Hamano wrote:
>>>> Philip Oakley <philipoakley@iee.email> writes:
>>>>
>>>>> An alternative in the other direction is to go with the 'not currently
>>>>> on any branch' (detached at nowhere) but then require users to
>>>>> deliberately create their first branch with their chosen name. This
>>>>> moves the 'backward incompatibility' to a different place, which may be
>>>>> easier to manage.
>>>> As has already been mentioned by Peff, I do not think that is a
>>>> workable alternative, especially given that people are generally
>>>> afraid of and easily get confused by being on a detached HEAD.
>>> Yes, our use of the technical phrase 'detached HEAD' is confusing,
>>> compared with the more pleasant 'not on any branch', or 'not at a branch
>>> tip'. Such is the curse of knowledge.
>> To me "not on a branch [tip]" is also confusing, as in fact you are, as
>> is easily seen after you perform a few commits, and now HEAD points
>> directly to the tip of the branch (that has no other references).
>>
>> I wonder why Git didn't rather adopt "unnamed branch" or "nameless
>> branch" to describe this mode of operation?
> Given the ephemeral nature of branches they sound like good
> suggestion.

Sure, so to me they sound even more natural in Git context than in any
other VCS I'm aware of.

>
> However I suspect "history" to be the "why" of the current 'detached
> head' usage.
> Maybe it's a side reference to Nearly Headless Nick or other discussions
> of the time (aka lost in history)?

I do have a few commits at which HEAD has been detached, not once at
some. Bloody they are.

-- Sergey
Junio C Hamano Nov. 21, 2020, 11:01 p.m. UTC | #44
Sergey Organov <sorganov@gmail.com> writes:

> To me "not on a branch [tip]" is also confusing, as in fact you are, as
> is easily seen after you perform a few commits, and now HEAD points
> directly to the tip of the branch (that has no other references).

Aren't you confused about what "on a branch" means?

After either of these two operations, your HEAD may point at the
same commit, but the former is on a branch (the master branch), and
the latter is not.

    git checkout master
    git checkout master^0

The difference between these two states does *NOT* come from which
commit HEAD points at.

The difference comes from what happens when you make a new commit
starting from that state.  The former (i.e. you are on a branch)
grows the branch.  The latter (i.e. you are not on a branch) does
not grow any branch.

This is an unrelated trivia, but did anybody know that we were
pretty much on the detached HEAD all the time for more than a month
of early life of Git, until cad88fdf (git-init-db: set up the full
default environment, 2005-05-30)?
Sergey Organov Nov. 22, 2020, 10:21 a.m. UTC | #45
Junio C Hamano <gitster@pobox.com> writes:

> Sergey Organov <sorganov@gmail.com> writes:
>
>> To me "not on a branch [tip]" is also confusing, as in fact you are, as
>> is easily seen after you perform a few commits, and now HEAD points
>> directly to the tip of the branch (that has no other references).
>
> Aren't you confused about what "on a branch" means?

I believe I'm not.

>
> After either of these two operations, your HEAD may point at the
> same commit, but the former is on a branch (the master branch), and
> the latter is not.
>
>     git checkout master
>     git checkout master^0
>
> The difference between these two states does *NOT* come from which
> commit HEAD points at.

Sure.

>
> The difference comes from what happens when you make a new commit
> starting from that state.  The former (i.e. you are on a branch)
> grows the branch.

Sure.

> The latter (i.e. you are not on a branch) does not grow any branch.

That's one way of looking at it, resulting in this "detached HEAD"
thingy that is too technical for the git user proper, I think. Moreover,
it immediately raises the question: if it doesn't grow any branch, /what/
does it grow?

Another way of describing it, that I prefer, is that you /are/ on an
/unnamed/ branch and new commits grow this particular /unnamed/ branch.
No need not only for "detached", but even for "HEAD" to be known to the
user to get the idea, I think.

>
> This is an unrelated trivia, but did anybody know that we were
> pretty much on the detached HEAD all the time for more than a month
> of early life of Git, until cad88fdf (git-init-db: set up the full
> default environment, 2005-05-30)?

I was not aware, and it seems that in my terminology it'd sound: "Git
didn't have named branches until cad88fdf".

-- Sergey
Philip Oakley Nov. 22, 2020, 11:20 a.m. UTC | #46
On 22/11/2020 10:21, Sergey Organov wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> Sergey Organov <sorganov@gmail.com> writes:
>>
>>> To me "not on a branch [tip]" is also confusing, as in fact you are, as
>>> is easily seen after you perform a few commits, and now HEAD points
>>> directly to the tip of the branch (that has no other references).
>> Aren't you confused about what "on a branch" means?
> I believe I'm not.

Isn't this one of those "implementation detail" viewpoint arguments,
combined with some incompleteness in various places.

From a naive english user perspective , 'on' a branch can also mean
anywhere along a branch and not just at the tip. Being at a commit along
a branch can be tricky to appreciate (that on/at distinction isn't
immediately obvious..)
>
>> After either of these two operations, your HEAD may point at the
>> same commit, but the former is on a branch (the master branch), and
>> the latter is not.
>>
>>     git checkout master
>>     git checkout master^0
>>
>> The difference between these two states does *NOT* come from which
>> commit HEAD points at.
> Sure.
From an implementation perspective one can go two ways, and we tell the
user which way we went, even though, ultimately, we look at the same
commit.

Though, for an unborn branch we don't have a null commit value (c.f.
empty tree) to help in being 'detached at nowhere'.
>
>> The difference comes from what happens when you make a new commit
>> starting from that state.  The former (i.e. you are on a branch)
>> grows the branch.
> Sure.
>
>> The latter (i.e. you are not on a branch) does not grow any branch.
> That's one way of looking at it, resulting in this "detached HEAD"
> thingy that is too technical for the git user proper, I think. Moreover,
> it immediately raises the question: if it doesn't grow any branch, /what/
> does it grow?
>
> Another way of describing it, that I prefer, is that you /are/ on an
> /unnamed/ branch and new commits grow this particular /unnamed/ branch.
> No need not only for "detached", but even for "HEAD" to be known to the
> user to get the idea, I think.
I don't think we can start like this and continue with a commit on top
of the orphaned 'unnamed' branch. (Not tried it though..)
>
>> This is an unrelated trivia, but did anybody know that we were
>> pretty much on the detached HEAD all the time for more than a month
>> of early life of Git, until cad88fdf (git-init-db: set up the full
>> default environment, 2005-05-30)?
> I was not aware, and it seems that in my terminology it'd sound: "Git
> didn't have named branches until cad88fdf".
>
> -- Sergey
Sergey Organov Nov. 22, 2020, 1:23 p.m. UTC | #47
Philip Oakley <philipoakley@iee.email> writes:

> On 22/11/2020 10:21, Sergey Organov wrote:
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>>> Sergey Organov <sorganov@gmail.com> writes:
>>>
>>>> To me "not on a branch [tip]" is also confusing, as in fact you are, as
>>>> is easily seen after you perform a few commits, and now HEAD points
>>>> directly to the tip of the branch (that has no other references).
>>> Aren't you confused about what "on a branch" means?
>> I believe I'm not.
>
> Isn't this one of those "implementation detail" viewpoint arguments,
> combined with some incompleteness in various places.
>
> From a naive english user perspective , 'on' a branch can also mean
> anywhere along a branch and not just at the tip. Being at a commit along
> a branch can be tricky to appreciate (that on/at distinction isn't
> immediately obvious..)
>>
>>> After either of these two operations, your HEAD may point at the
>>> same commit, but the former is on a branch (the master branch), and
>>> the latter is not.
>>>
>>>     git checkout master
>>>     git checkout master^0
>>>
>>> The difference between these two states does *NOT* come from which
>>> commit HEAD points at.
>> Sure.
> From an implementation perspective one can go two ways, and we tell the
> user which way we went, even though, ultimately, we look at the same
> commit.

AFAIU, the only difference is that HEAD points to the commit directly in
the case of "detached HEAD", while it points to the commit indirectly
through the branch reference in the usual case.

>
> Though, for an unborn branch we don't have a null commit value (c.f.
> empty tree) to help in being 'detached at nowhere'.

We can pretend we have a null commit for the sake of regularity, even
though Git implementation has none.

Actually, it looks like a few things would be easier if Git got the
"Adam" commit that is the ultimate final parent of everything in the
first place, but it didn't.


>>
>>> The difference comes from what happens when you make a new commit
>>> starting from that state.  The former (i.e. you are on a branch)
>>> grows the branch.
>> Sure.
>>
>>> The latter (i.e. you are not on a branch) does not grow any branch.
>> That's one way of looking at it, resulting in this "detached HEAD"
>> thingy that is too technical for the git user proper, I think. Moreover,
>> it immediately raises the question: if it doesn't grow any branch, /what/
>> does it grow?
>>
>> Another way of describing it, that I prefer, is that you /are/ on an
>> /unnamed/ branch and new commits grow this particular /unnamed/ branch.
>> No need not only for "detached", but even for "HEAD" to be known to the
>> user to get the idea, I think.
> I don't think we can start like this and continue with a commit on top
> of the orphaned 'unnamed' branch. (Not tried it though..)

I rather believe we can, no problems, and that's why "detached HEAD" behaves
exactly as unnamed branch would.

To make it obvious "detached HEAD" is in fact a subset of the usual
case, imagine that "detached HEAD" is rather first implemented by
pointing to a branch reference with a hidden name that in turn points to
the commit, and then this "incognito branch reference" is optimized-out
as being invisible anyway, so HEAD now points to the commit itself.

-- Sergey Organov
Philip Oakley Nov. 22, 2020, 8:18 p.m. UTC | #48
On 22/11/2020 13:23, Sergey Organov wrote:
>>>> The latter (i.e. you are not on a branch) does not grow any branch.
>>> That's one way of looking at it, resulting in this "detached HEAD"
>>> thingy that is too technical for the git user proper, I think. Moreover,
>>> it immediately raises the question: if it doesn't grow any branch, /what/
>>> does it grow?
>>>
>>> Another way of describing it, that I prefer, is that you /are/ on an
>>> /unnamed/ branch and new commits grow this particular /unnamed/ branch.
>>> No need not only for "detached", but even for "HEAD" to be known to the
>>> user to get the idea, I think.
>> I don't think we can start like this and continue with a commit on top
>> of the orphaned 'unnamed' branch. (Not tried it though..)
> I rather believe we can, no problems, and that's why "detached HEAD" behaves
> exactly as unnamed branch would.
>
> To make it obvious "detached HEAD" is in fact a subset of the usual
> case, imagine that "detached HEAD" is rather first implemented by
> pointing to a branch reference with a hidden name that in turn points to
> the commit, and then this "incognito branch reference" is optimized-out
> as being invisible anyway, so HEAD now points to the commit itself.
>
Thinking about some options...

After a `git init`: We can hack HEAD to "ref: refs/heads/" (i.e. a
symref to an unnamed branch) and `git status` will report "No commits yet".
My PS1 will report the current branch as "()" (i.e. an empty name).

However,
`git branch` reports "Failed to resolve HEAD as a valid ref.", and
`git commit` reports "cannot lock ref 'HEAD': there is a non-empty
directory '.git/refs/heads/' blocking reference 'refs/heads/'".

So, there could be the option to detect that unnamed ref state (no
characters after the final "/") without going "Fatal:".

However there is still the potential difficulty that after the first
commit on that unnamed branch we would have the difficult choice of:

- either keeping that unnamed ref/branch symref, and have nowhere to
hold the new commit name (oid), because HEAD is already acting as the
place holder for the symref,
- or we have to lose the place holder symref and place the new commit
oid into HEAD, leaving us back at the regular "detached head", but for
an as yet unnamed orphan branch.
(tested on Windows[1])

For the second case we would still need to ensure that  protections are
in place to avoid loosing those detached commits if the user
switches/checks out to new branch based on some other oid. (for that to
happen then that checkout oid must be somewhere in the unnamed branch,
but the latest tip commits should need checking to prevent unexpected
loss - the current warning may not be enough...)

At the moment there is a lot of 'lock-in' for the status quo, and the
alternative may not be any better, and have some backward compatibility
issues, though those may be overstated, depending on how repos are being
'shared'.

Philip


[1]
phili@Philip-Win10 MINGW64 /c/git-sdk-64/usr/src/unnamed ()
$ git version
git version 2.29.2.windows.2
Felipe Contreras Nov. 22, 2020, 9:56 p.m. UTC | #49
On Sun, Nov 22, 2020 at 4:24 AM Sergey Organov <sorganov@gmail.com> wrote:
>
> Junio C Hamano <gitster@pobox.com> writes:

> > The latter (i.e. you are not on a branch) does not grow any branch.
>
> That's one way of looking at it, resulting in this "detached HEAD"
> thingy that is too technical for the git user proper, I think. Moreover,
> it immediately raises the question: if it doesn't grow any branch, /what/
> does it grow?
>
> Another way of describing it, that I prefer, is that you /are/ on an
> /unnamed/ branch and new commits grow this particular /unnamed/ branch.
> No need not only for "detached", but even for "HEAD" to be known to the
> user to get the idea, I think.

This is precisely what it is conceptually.

And there's absolutely no need for the user to know what HEAD is
behind the curtains, especially since they can just use @, and think
of it as "the current branch".

It is clearly a branch, for example you can do "git push origin @:my-fix".

Cheers.
Junio C Hamano Nov. 22, 2020, 11:54 p.m. UTC | #50
Felipe Contreras <felipe.contreras@gmail.com> writes:

> It is clearly a branch, for example you can do "git push origin @:my-fix".

Hmm, you can also do "git push origin c2f3bf071e:maintenance", but
it does not make a bare object name a branch.  

At least I doubt the "clearly" part of your statement.  There might
be a better example to support the above claim, but this one is not.