git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* What's cooking in git.git (Jul 2017, #01; Wed, 5)
@ 2017-07-05 22:35 Junio C Hamano
  2017-07-05 23:06 ` Stefan Beller
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Junio C Hamano @ 2017-07-05 22:35 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.  The ones marked with '.' do not appear in any of
the integration branches, but I am still holding onto them.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* bw/repo-object (2017-06-23) 21 commits
  (merged to 'next' on 2017-06-26 at ed9c0b77c3)
 + ls-files: use repository object
 + repository: enable initialization of submodules
 + submodule: convert is_submodule_initialized to work on a repository
 + submodule: add repo_read_gitmodules
 + submodule-config: store the_submodule_cache in the_repository
 + repository: add index_state to struct repo
 + config: read config from a repository object
 + path: add repo_worktree_path and strbuf_repo_worktree_path
 + path: add repo_git_path and strbuf_repo_git_path
 + path: worktree_git_path() should not use file relocation
 + path: convert do_git_path to take a 'struct repository'
 + path: convert strbuf_git_common_path to take a 'struct repository'
 + path: always pass in commondir to update_common_dir
 + path: create path.h
 + environment: store worktree in the_repository
 + environment: place key repository state in the_repository
 + repository: introduce the repository object
 + environment: remove namespace_len variable
 + setup: add comment indicating a hack
 + setup: don't perform lazy initialization of repository state
 + Merge branches 'bw/ls-files-sans-the-index' and 'bw/config-h' into bw/repo-object

 Introduce a "repository" object to eventually make it easier to
 work in multiple repositories (the primary focus is to work with
 the superproject and its submodules) in a single process.


* cc/shared-index-permfix (2017-06-25) 3 commits
  (merged to 'next' on 2017-06-26 at bb41584bf0)
 + t1700: make sure split-index respects core.sharedrepository
 + t1301: move modebits() to test-lib-functions.sh
 + read-cache: use shared perms when writing shared index

 The split index code did not honor core.sharedrepository setting
 correctly.


* jt/unify-object-info (2017-06-26) 8 commits
  (merged to 'next' on 2017-06-26 at 540ea81983)
 + sha1_file: refactor has_sha1_file_with_flags
 + sha1_file: do not access pack if unneeded
 + sha1_file: teach sha1_object_info_extended more flags
 + sha1_file: refactor read_object
 + sha1_file: move delta base cache code up
 + sha1_file: rename LOOKUP_REPLACE_OBJECT
 + sha1_file: rename LOOKUP_UNKNOWN_OBJECT
 + sha1_file: teach packed_object_info about typename

 Code clean-ups.


* rs/sha1-name-readdir-optim (2017-06-24) 4 commits
  (merged to 'next' on 2017-06-26 at a70587f2b9)
 + sha1_file: guard against invalid loose subdirectory numbers
 + sha1_file: let for_each_file_in_obj_subdir() handle subdir names
 + p4205: add perf test script for pretty log formats
 + sha1_name: cache readdir(3) results in find_short_object_filename()

 Optimize "what are the object names already taken in an alternate
 object database?" query that is used to derive the length of prefix
 an object name is uniquely abbreviated to.

--------------------------------------------------
[New Topics]

* bc/object-id (2017-07-04) 12 commits
 - sha1_name: convert GET_SHA1* flags to GET_OID*
 - sha1_name: convert get_sha1* to get_oid*
 - Convert remaining callers of get_sha1 to get_oid.
 - builtin/verify-tag: convert to struct object_id
 - builtin/unpack-file: convert to struct object_id
 - bisect: convert bisect_checkout to struct object_id
 - builtin/update_ref: convert to struct object_id
 - sequencer: convert to struct object_id
 - remote: convert struct push_cas to struct object_id
 - submodule: convert submodule config lookup to use object_id
 - builtin/merge-tree: convert remaining caller of get_sha1 to object_id
 - builtin/fsck: convert remaining caller of get_sha1 to object_id

 Conversion from uchar[20] to struct object_id continues.


* jk/reflog-walk (2017-07-05) 7 commits
 - reflog-walk: stop using fake parents
 - rev-list: check reflog_info before showing usage
 - get_revision_1(): replace do-while with an early return
 - log: do not free parents when walking reflog
 - [SQUASH LOG MESSAGE ONLY] t1414: document some reflog-walk oddities
 - t1414: document some reflog-walk oddities
 - Merge branch 'jk/reflog-walk-maint' into jk/reflog-walk
 (this branch uses jk/reflog-walk-maint.)

 Numerous bugs in walking of reflogs via "log -g" and friends have
 been fixed.


* jk/reflog-walk-maint (2017-07-05) 1 commit
 - reflog-walk: skip over double-null oid due to HEAD rename
 (this branch is used by jk/reflog-walk.)

 After "git branch --move" of the currently checked out branch, the
 code to walk the reflog of HEAD via "log -g" and friends
 incorrectly stopped at the reflog entry that records the renaming
 of the branch.


* js/t5534-rev-parse-gives-multi-line-output-fix (2017-07-05) 1 commit
  (merged to 'next' on 2017-07-05 at 5f964c44ba)
 + t5534: fix misleading grep invocation

 A few tests that tried to verify the contents of push certificates
 did not use 'git rev-parse' to formulate the line to look for in
 the certificate correctly.

 Will merge to 'master'.


* rs/apply-avoid-over-reading (2017-07-01) 1 commit
  (merged to 'next' on 2017-07-05 at 35730f3a47)
 + apply: use starts_with() in gitdiff_verify_name()

 Code clean-up to fix possible buffer over-reading.

 Will merge to 'master'.


* sb/hashmap-cleanup (2017-07-05) 10 commits
 - t/helper/test-hashmap: use custom data instead of duplicate cmp functions
 - name-hash.c: drop hashmap_cmp_fn cast
 - submodule-config.c: drop hashmap_cmp_fn cast
 - remote.c: drop hashmap_cmp_fn cast
 - patch-ids.c: drop hashmap_cmp_fn cast
 - convert/sub-process: drop cast to hashmap_cmp_fn
 - config.c: drop hashmap_cmp_fn cast
 - builtin/describe: drop hashmap_cmp_fn cast
 - builtin/difftool.c: drop hashmap_cmp_fn cast
 - attr.c: drop hashmap_cmp_fn cast
 (this branch uses sb/hashmap-customize-comparison; is tangled with sb/diff-color-move.)

 Many uses of comparision callback function the hashmap API uses
 cast the callback function type when registering it to
 hashmap_init(), which defeats the compile time type checking when
 the callback interface changes (e.g. gaining more parameters).
 The callback implementations have been updated to take "void *"
 pointers and cast them to the type they expect instead.

 Will wait for feedback, then merge to and cook in 'next'.


* tb/push-to-cygwin-unc-path (2017-07-05) 1 commit
 - cygwin: allow pushing to UNC paths

 On Cygwin, similar to Windows, "git push //server/share/repository"
 ought to mean a repository on a network share that can be accessed
 locally, but this did not work correctly due to stripping the double
 slashes at the beginning.

 This may need to be heavily tested before it gets unleashed to the
 wild, as the change is at a fairly low-level code and would affect
 not just the code to decide if the push destination is local.  There
 may be unexpected fallouts in the path normalization.

 Will wait for feedback, then merge to and cook in 'next'.


* ab/sha1dc-maint (2017-07-03) 1 commit
  (merged to 'next' on 2017-07-05 at ac69c90b7e)
 + sha1dc: update from upstream
 (this branch is used by ab/sha1dc.)

 Update the sha1dc again to fix portability glitches.

 Will merge to 'master'.

--------------------------------------------------
[Stalled]

* mg/status-in-progress-info (2017-05-10) 2 commits
 - status --short --inprogress: spell it as --in-progress
 - status: show in-progress info for short status

 "git status" learns an option to report various operations
 (e.g. "merging") that the user is in the middle of.

 cf. <xmqqmvakcdqw.fsf@gitster.mtv.corp.google.com>


* nd/worktree-move (2017-04-20) 6 commits
 - worktree remove: new command
 - worktree move: refuse to move worktrees with submodules
 - worktree move: accept destination as directory
 - worktree move: new command
 - worktree.c: add update_worktree_location()
 - worktree.c: add validate_worktree()

 "git worktree" learned move and remove subcommands.

 Expecting a reroll.
 cf. <20170420101024.7593-1-pclouds@gmail.com>
 cf. <20170421145916.mknekgqzhxffu7di@sigill.intra.peff.net>
 cf. <d0e81b1e-5869-299e-f462-4d43dc997bd1@ramsayjones.plus.com>


* xz/send-email-batch-size (2017-07-05) 1 commit
  (merged to 'next' on 2017-07-05 at 92f3c31fbd)
 + send-email: --batch-size to work around some SMTP server limit

 "git send-email" learned to overcome some SMTP server limitation
 that does not allow many pieces of e-mails to be sent over a single
 session.

 Will merge to 'master'.


* sg/clone-refspec-from-command-line-config (2017-06-16) 2 commits
 - Documentation/clone: document ignored configuration variables
 - clone: respect additional configured fetch refspecs during initial fetch
 (this branch is used by sg/remote-no-string-refspecs.)

 "git clone -c var=val" is a way to set configuration variables in
 the resulting repository, but it is more useful to also make these
 variables take effect while the initial clone is happening,
 e.g. these configuration variables could be fetch refspecs.

 Waiting for a response.
 cf. <20170617112228.vugswym4o4owf6wj@sigill.intra.peff.net>
 cf. <xmqqmv8zhdap.fsf@gitster.mtv.corp.google.com>


* js/rebase-i-final (2017-06-15) 10 commits
 - rebase -i: rearrange fixup/squash lines using the rebase--helper
 - t3415: test fixup with wrapped oneline
 - rebase -i: skip unnecessary picks using the rebase--helper
 - rebase -i: check for missing commits in the rebase--helper
 - t3404: relax rebase.missingCommitsCheck tests
 - rebase -i: also expand/collapse the SHA-1s via the rebase--helper
 - rebase -i: do not invent onelines when expanding/collapsing SHA-1s
 - rebase -i: remove useless indentation
 - rebase -i: generate the script via rebase--helper
 - t3415: verify that an empty instructionFormat is handled as before

 The final batch to "git rebase -i" updates to move more code from
 the shell script to C.

 Expecting a reroll.
 This is at its v5.
 cf. <cover.1497444257.git.johannes.schindelin@gmx.de>

--------------------------------------------------
[Cooking]

* ab/grep-lose-opt-regflags (2017-06-30) 6 commits
  (merged to 'next' on 2017-07-05 at 375c0b92ea)
 + grep: remove redundant REG_NEWLINE when compiling fixed regex
 + grep: remove regflags from the public grep_opt API
 + grep: remove redundant and verbose re-assignments to 0
 + grep: remove redundant "fixed" field re-assignment to 0
 + grep: adjust a redundant grep pattern type assignment
 + grep: remove redundant double assignment to 0

 Code cleanup.

 Will merge to 'master'.


* ks/commit-assuming-only-warning-removal (2017-06-30) 2 commits
  (merged to 'next' on 2017-07-05 at 462a72df95)
 + commit-template: distinguish status information unconditionally
 + commit-template: remove outdated notice about explicit paths

 An old message shown in the commit log template was removed, as it
 has outlived its usefulness.

 Will merge to 'master'.


* sb/hashmap-customize-comparison (2017-06-30) 3 commits
 - hashmap: migrate documentation from Documentation/technical into header
 - patch-ids.c: use hashmap correctly
 - hashmap.h: compare function has access to a data field
 (this branch is used by sb/diff-color-move and sb/hashmap-cleanup.)

 Update the hashmap API so that data to customize the behaviour of
 the comparison function can be specified at the time a hashmap is
 initialized.

 Will merge to 'next'.


* sb/merge-recursive-code-cleanup (2017-06-30) 1 commit
  (merged to 'next' on 2017-07-05 at 4228240520)
 + merge-recursive: use DIFF_XDL_SET macro

 Code clean-up.

 Will merge to 'master'.


* ab/strbuf-addftime-tzname-boolify (2017-07-01) 2 commits
  (merged to 'next' on 2017-07-05 at 81e6795eb3)
 + strbuf: change an always NULL/"" strbuf_addftime() param to bool
 + strbuf.h comment: discuss strbuf_addftime() arguments in order

 strbuf_addftime() is further getting tweaked.

 Will merge to 'master'.


* mt/p4-parse-G-output (2017-07-05) 1 commit
 - git-p4: parse marshal output "p4 -G" in p4 changes

 Use "p4 -G" to make "p4 changes" output more Python-friendly
 to parse.

 Needs review/ack from git-p4 folks.


* aw/contrib-subtree-doc-asciidoctor (2017-06-27) 1 commit
  (merged to 'next' on 2017-06-30 at af23bd111b)
 + subtree: honour USE_ASCIIDOCTOR when set

 The Makefile rule in contrib/subtree for building documentation
 learned to honour USE_ASCIIDOCTOR just like the main documentation
 set does.

 Will merge to 'master'.


* js/fsck-name-object (2017-06-28) 1 commit
  (merged to 'next' on 2017-06-30 at 9a08514cf2)
 + t1450: use egrep for regexp "alternation"

 Test fix.

 Will merge to 'master'.


* jc/utf8-fprintf (2017-06-28) 1 commit
  (merged to 'next' on 2017-06-30 at a8cc490818)
 + submodule--helper: do not call utf8_fprintf() unnecessarily

 Code cleanup.

 Will merge to 'master'.


* rs/free-and-null (2017-06-29) 1 commit
 - coccinelle: polish FREE_AND_NULL rules

 Code cleanup.


* ab/wildmatch (2017-06-23) 1 commit
 - wildmatch: remove unused wildopts parameter

 Prepare the wildmatch API for future enhancements to allow a
 pattern that is repeatedly matched against many strings to be
 precompiled.


* ex/deprecate-empty-pathspec-as-match-all (2017-06-23) 2 commits
  (merged to 'next' on 2017-06-26 at d026281517)
 + pathspec: die on empty strings as pathspec
 + t0027: do not use an empty string as a pathspec element

 The final step to make an empty string as a pathspec element
 illegal.  We started this by first deprecating and warning a
 pathspec that has such an element in 2.11 (Nov 2016).

 Hopefully we can merge this down to the 'master' by the end of the
 year?  A deprecation warning period that is about 1 year does not
 sound too bad.

 Will cook in 'next'.


* sb/pull-rebase-submodule (2017-06-27) 4 commits
 - builtin/fetch cleanup: always set default value for submodule recursing
 - pull: optionally rebase submodules (remote submodule changes only)
 - builtin/fetch: parse recurse-submodules-default at default options parsing
 - builtin/fetch: factor submodule recurse parsing out to submodule config

 "git pull --rebase --recurse-submodules" learns to rebase the
 branch in the submodules to an updated base.


* pw/unquote-path-in-git-pm (2017-06-30) 4 commits
  (merged to 'next' on 2017-07-05 at 538ab4d599)
 + t9700: add tests for Git::unquote_path()
 + Git::unquote_path(): throw an exception on bad path
 + Git::unquote_path(): handle '\a'
 + add -i: move unquote_path() to Git.pm

 Code refactoring.

 Will merge to 'master'.


* mh/packed-ref-store (2017-07-03) 30 commits
  (merged to 'next' on 2017-07-05 at 6c68c603cc)
 + read_packed_refs(): die if `packed-refs` contains bogus data
 + t3210: add some tests of bogus packed-refs file contents
 + repack_without_refs(): don't lock or unlock the packed refs
 + commit_packed_refs(): remove call to `packed_refs_unlock()`
 + clear_packed_ref_cache(): don't protest if the lock is held
 + packed_refs_unlock(), packed_refs_is_locked(): new functions
 + packed_refs_lock(): report errors via a `struct strbuf *err`
 + packed_refs_lock(): function renamed from lock_packed_refs()
 + commit_packed_refs(): use a staging file separate from the lockfile
 + commit_packed_refs(): report errors rather than dying
 + packed_ref_store: make class into a subclass of `ref_store`
 + packed-backend: new module for handling packed references
 + packed_read_raw_ref(): new function, replacing `resolve_packed_ref()`
 + packed_ref_store: support iteration
 + packed_peel_ref(): new function, extracted from `files_peel_ref()`
 + repack_without_refs(): take a `packed_ref_store *` parameter
 + get_packed_ref(): take a `packed_ref_store *` parameter
 + rollback_packed_refs(): take a `packed_ref_store *` parameter
 + commit_packed_refs(): take a `packed_ref_store *` parameter
 + lock_packed_refs(): take a `packed_ref_store *` parameter
 + add_packed_ref(): take a `packed_ref_store *` parameter
 + get_packed_refs(): take a `packed_ref_store *` parameter
 + get_packed_ref_cache(): take a `packed_ref_store *` parameter
 + validate_packed_ref_cache(): take a `packed_ref_store *` parameter
 + clear_packed_ref_cache(): take a `packed_ref_store *` parameter
 + packed_ref_store: move `packed_refs_lock` member here
 + packed_ref_store: move `packed_refs_path` here
 + packed_ref_store: new struct
 + add_packed_ref(): teach function to overwrite existing refs
 + t1408: add a test of stale packed refs covered by loose refs

 The "ref-store" code reorganization continues.

 Will merge to 'master'.


* sb/submodule-doc (2017-06-22) 1 commit
 - submodules: overhaul documentation

 Doc update.

 What's the status of this thing?


* sd/branch-copy (2017-06-18) 3 commits
 - branch: add a --copy (-c) option to go with --move (-m)
 - branch: add test for -m renaming multiple config sections
 - config: create a function to format section headers

 "git branch" learned "-c/-C" to create and switch to a new branch
 by copying an existing one.

 Has a bit of interaction with mh/packed-ref-store and bw/config-h,
 so perhaps needs to wait for the former to stabilize a bit more
 and possibly rebasing on them.


* ls/filter-process-delayed (2017-06-30) 7 commits
  (merged to 'next' on 2017-07-05 at a35e644082)
 + convert: add "status=delayed" to filter process protocol
 + convert: refactor capabilities negotiation
 + convert: move multiple file filter error handling to separate function
 + convert: put the flags field before the flag itself for consistent style
 + t0021: write "OUT <size>" only on success
 + t0021: make debug log file name configurable
 + t0021: keep filter log files on comparison

 The filter-process interface learned to allow a process with long
 latency give a "delayed" response.

 Will merge to 'master'.


* ab/sha1dc (2017-07-03) 2 commits
 - sha1collisiondetection: automatically enable when submodule is populated
 - sha1dc: optionally use sha1collisiondetection as a submodule
 (this branch uses ab/sha1dc-maint.)

 The "collission-detecting" implementation of SHA-1 hash we borrowed
 from is replaced by directly binding the upstream project as our
 submodule.  Glitches on minority platforms are still being worked out.

 Will merge to 'next'.


* bp/fsmonitor (2017-06-12) 6 commits
 - fsmonitor: add a sample query-fsmonitor hook script for Watchman
 - fsmonitor: add documentation for the fsmonitor extension.
 - fsmonitor: add test cases for fsmonitor extension
 - fsmonitor: teach git to optionally utilize a file system monitor to speed up detecting new or changed files.
 - dir: make lookup_untracked() available outside of dir.c
 - bswap: add 64 bit endianness helper get_be64

 We learned to talk to watchman to speed up "git status".

 No more comments or updates?


* sb/diff-color-move (2017-06-30) 26 commits
 - diff: document the new --color-moved setting
 - diff.c: add dimming to moved line detection
 - diff.c: color moved lines differently, plain mode
 - diff.c: color moved lines differently
 - diff.c: buffer all output if asked to
 - diff.c: emit_diff_symbol learns about DIFF_SYMBOL_SUMMARY
 - diff.c: emit_diff_symbol learns about DIFF_SYMBOL_STAT_SEP
 - diff.c: convert word diffing to use emit_diff_symbol
 - diff.c: convert show_stats to use emit_diff_symbol
 - diff.c: convert emit_binary_diff_body to use emit_diff_symbol
 - submodule.c: migrate diff output to use emit_diff_symbol
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_REWRITE_DIFF
 - diff.c: emit_diff_symbol learns about DIFF_SYMBOL_BINARY_FILES
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_HEADER
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_FILEPAIR_{PLUS, MINUS}
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_CONTEXT_INCOMPLETE
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_WORDS[_PORCELAIN]
 - diff.c: migrate emit_line_checked to use emit_diff_symbol
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_NO_LF_EOF
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_CONTEXT_FRAGINFO
 - diff.c: emit_diff_symbol learns DIFF_SYMBOL_CONTEXT_MARKER
 - diff.c: introduce emit_diff_symbol
 - diff.c: factor out diff_flush_patch_all_file_pairs
 - diff.c: move line ending check into emit_hunk_header
 - diff.c: readability fix
 - Merge branch 'sb/hashmap-customize-comparison' into sb/diff-color-move
 (this branch uses sb/hashmap-customize-comparison; is tangled with sb/hashmap-cleanup.)

 "git diff" has been taught to optionally paint new lines that are
 the same as deleted lines elsewhere differently from genuinely new
 lines.

 Will merge to 'next'.

--------------------------------------------------
[Discarded]

* mh/packed-ref-store-prep-extra (2017-06-18) 1 commit
 . prefix_ref_iterator_advance(): relax the check of trim length

 Split out of mh/packed-ref-store-prep.


* nd/prune-in-worktree (2017-04-24) 12 commits
 . rev-list: expose and document --single-worktree
 . revision.c: --reflog add HEAD reflog from all worktrees
 . files-backend: make reflog iterator go through per-worktree reflog
 . revision.c: --all adds HEAD from all worktrees
 . refs: remove dead for_each_*_submodule()
 . revision.c: use refs_for_each*() instead of for_each_*_submodule()
 . refs: add refs_head_ref()
 . refs: move submodule slash stripping code to get_submodule_ref_store
 . refs.c: refactor get_submodule_ref_store(), share common free block
 . revision.c: --indexed-objects add objects from all worktrees
 . revision.c: refactor add_index_objects_to_pending()
 . revision.h: new flag in struct rev_info wrt. worktree-related refs

 "git gc" and friends when multiple worktrees are used off of a
 single repository did not consider the index and per-worktree refs
 of other worktrees as the root for reachability traversal, making
 objects that are in use only in other worktrees to be subject to
 garbage collection.


* ab/free-and-null (2017-06-28) 2 commits
  (merged to 'next' on 2017-06-28 at 1cf373c61a)
 + Revert "coccinelle: add a rule to make "expression" code use FREE_AND_NULL()"
  (merged to 'next' on 2017-06-28 at 1785f88122)
 + coccinelle: add a rule to make "expression" code use FREE_AND_NULL()

 The coccinelle rule for free-and-null refactoring got simplified.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: What's cooking in git.git (Jul 2017, #01; Wed, 5)
  2017-07-05 22:35 What's cooking in git.git (Jul 2017, #01; Wed, 5) Junio C Hamano
@ 2017-07-05 23:06 ` Stefan Beller
  2017-07-07  2:13   ` Junio C Hamano
  2017-07-05 23:14 ` [PATCH v2 0/3] branch: add a --copy to go with --move Ævar Arnfjörð Bjarmason
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Stefan Beller @ 2017-07-05 23:06 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org

> [Graduated to "master"]
>
> * bw/repo-object (2017-06-23) 21 commits
...
>
>  Introduce a "repository" object to eventually make it easier to
>  work in multiple repositories (the primary focus is to work with
>  the superproject and its submodules) in a single process.

It's pretty rad to see this advancing to master.
FYI: I started working on teaching the object store how to work
with repository objects. This would allow us to get rid of hacks in
submodule.c: namely add_submodule_odb, which adds submodule
objects to the (main) object store for processing. Ideally we want
to free the objects of a submodule once we are done with a submodule.
(or integrate it into our try_to_free_routine)

> * sb/hashmap-cleanup (2017-07-05) 10 commits
...
>  Will wait for feedback, then merge to and cook in 'next'.

Thanks.

> * sb/pull-rebase-submodule (2017-06-27) 4 commits
>  - builtin/fetch cleanup: always set default value for submodule recursing
>  - pull: optionally rebase submodules (remote submodule changes only)
>  - builtin/fetch: parse recurse-submodules-default at default options parsing
>  - builtin/fetch: factor submodule recurse parsing out to submodule config
>
>  "git pull --rebase --recurse-submodules" learns to rebase the
>  branch in the submodules to an updated base.

Speaking of submodules, It's not just features, but I also send bug fixes. ;)
https://public-inbox.org/git/20170630003851.17288-1-sbeller@google.com/
(That patch is not related to this series, except for working in the submodule
area, but I consider that patch more important than e.g. this series.)

> * sb/submodule-doc (2017-06-22) 1 commit
>  - submodules: overhaul documentation
>
>  Doc update.
>
>  What's the status of this thing?

There was some review on the list (mostly from Brandon and Jonathan T.),
but I felt like it was bikeshedding, as there is no black/white correctness
with words. (Same for code, but for code it is easier to come to a
consensus at least.)

So I had a couple of internal rounds with them on a Google doc, hence
I assume they agree on this patch being ok as-is.  But it has been a while
I can reread it myself to check. But I guess most valuable input
would come from others.

> * sb/diff-color-move (2017-06-30) 26 commits
...
>  Will merge to 'next'.

cool. Let's see how a larger audience reacts to this one. Maybe there
is more input for a good heuristic.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 0/3] branch: add a --copy to go with --move
  2017-07-05 22:35 What's cooking in git.git (Jul 2017, #01; Wed, 5) Junio C Hamano
  2017-07-05 23:06 ` Stefan Beller
@ 2017-07-05 23:14 ` Ævar Arnfjörð Bjarmason
  2017-07-06  0:37   ` Junio C Hamano
  2017-07-05 23:14 ` [PATCH v2 1/3] config: create a function to format section headers Ævar Arnfjörð Bjarmason
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2017-07-05 23:14 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Sahil Dua, Jonathan Nieder, Michael Haggerty,
	Brandon Williams, Ævar Arnfjörð Bjarmason

On Wed, Jul 05 2017, Junio C. Hamano jotted:

> * sd/branch-copy (2017-06-18) 3 commits
>  - branch: add a --copy (-c) option to go with --move (-m)
>  - branch: add test for -m renaming multiple config sections
>  - config: create a function to format section headers
>
>  "git branch" learned "-c/-C" to create and switch to a new branch
>  by copying an existing one.
>
>  Has a bit of interaction with mh/packed-ref-store and bw/config-h,
>  so perhaps needs to wait for the former to stabilize a bit more
>  and possibly rebasing on them.

Now that bw/config-h has landed in master here's a version that's
rebased on that. No changes from v1 except:

 - moving the new config header addition from cache.h to config.h,
   corresponding to what was done in bw/config-h.

 - fixing a trivial comment whitespace issue which I see you applied
   locally.

Even though this modifies some of the same files as
mh/packed-ref-store it looks to me like this doesn't conflict with
that topic in any meaningful way, but I may be missing something. I
can't get a merge between this & gitster/mh/packed-ref-store
compiling, but that's due to issues in the latter which seem to be
fixed by some subsequent merge/fixup in pu, not something to do with a
genuine conflict with this topic.

Hopefully this'll allow this topic to land in 2.14.

Sahil Dua (2):
  config: create a function to format section headers
  branch: add a --copy (-c) option to go with --move (-m)

Ævar Arnfjörð Bjarmason (1):
  branch: add test for -m renaming multiple config sections

 Documentation/git-branch.txt |  14 ++-
 builtin/branch.c             |  67 ++++++++---
 config.c                     | 115 +++++++++++++++----
 config.h                     |   2 +
 refs.c                       |  11 ++
 refs.h                       |   9 +-
 refs/files-backend.c         |  46 ++++++--
 refs/refs-internal.h         |   4 +
 t/t3200-branch.sh            | 256 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 476 insertions(+), 48 deletions(-)

-- 
2.13.1.611.g7e3b11ae1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 1/3] config: create a function to format section headers
  2017-07-05 22:35 What's cooking in git.git (Jul 2017, #01; Wed, 5) Junio C Hamano
  2017-07-05 23:06 ` Stefan Beller
  2017-07-05 23:14 ` [PATCH v2 0/3] branch: add a --copy to go with --move Ævar Arnfjörð Bjarmason
@ 2017-07-05 23:14 ` Ævar Arnfjörð Bjarmason
  2017-07-05 23:14 ` [PATCH v2 2/3] branch: add test for -m renaming multiple config sections Ævar Arnfjörð Bjarmason
  2017-07-05 23:14 ` [PATCH v2 3/3] branch: add a --copy (-c) option to go with --move (-m) Ævar Arnfjörð Bjarmason
  4 siblings, 0 replies; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2017-07-05 23:14 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Sahil Dua, Jonathan Nieder, Michael Haggerty,
	Brandon Williams, Ævar Arnfjörð Bjarmason,
	Ramsay Jones

From: Sahil Dua <sahildua2305@gmail.com>

Factor out the logic which creates section headers in the config file,
e.g. the 'branch.foo' key will be turned into '[branch "foo"]'.

This introduces no function changes, but is needed for a later change
which adds support for copying branch sections in the config file.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Sahil Dua <sahildua2305@gmail.com>
---
 config.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/config.c b/config.c
index 4638b0696a..b7afb5941b 100644
--- a/config.c
+++ b/config.c
@@ -2244,10 +2244,10 @@ static int write_error(const char *filename)
 	return 4;
 }
 
-static int store_write_section(int fd, const char *key)
+static struct strbuf store_create_section(const char *key)
 {
 	const char *dot;
-	int i, success;
+	int i;
 	struct strbuf sb = STRBUF_INIT;
 
 	dot = memchr(key, '.', store.baselen);
@@ -2263,6 +2263,15 @@ static int store_write_section(int fd, const char *key)
 		strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
 	}
 
+	return sb;
+}
+
+static int store_write_section(int fd, const char *key)
+{
+	int success;
+
+	struct strbuf sb = store_create_section(key);
+
 	success = write_in_full(fd, sb.buf, sb.len) == sb.len;
 	strbuf_release(&sb);
 
-- 
2.13.1.611.g7e3b11ae1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 2/3] branch: add test for -m renaming multiple config sections
  2017-07-05 22:35 What's cooking in git.git (Jul 2017, #01; Wed, 5) Junio C Hamano
                   ` (2 preceding siblings ...)
  2017-07-05 23:14 ` [PATCH v2 1/3] config: create a function to format section headers Ævar Arnfjörð Bjarmason
@ 2017-07-05 23:14 ` Ævar Arnfjörð Bjarmason
  2017-07-05 23:14 ` [PATCH v2 3/3] branch: add a --copy (-c) option to go with --move (-m) Ævar Arnfjörð Bjarmason
  4 siblings, 0 replies; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2017-07-05 23:14 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Sahil Dua, Jonathan Nieder, Michael Haggerty,
	Brandon Williams, Ævar Arnfjörð Bjarmason

Add a test for how 'git branch -m' handles the renaming of multiple
config sections existing for one branch.

The config format we use is hybrid machine/human editable, and we do
our best to preserve the likes of comments and formatting when editing
the file with git-config.

This adds a test for the currently expected semantics in the face of
some rather obscure edge cases which are unlikely to occur in
practice.

Helped-by: Sahil Dua <sahildua2305@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Sahil Dua <sahildua2305@gmail.com>
---
 t/t3200-branch.sh | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 48d152b9a9..596fbc8483 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -358,6 +358,47 @@ test_expect_success 'config information was renamed, too' '
 	test_must_fail git config branch.s/s.dummy
 '
 
+test_expect_success 'git branch -m correctly renames multiple config sections' '
+	test_when_finished "git checkout master" &&
+	git checkout -b source master &&
+
+	# Assert that a config file with multiple config sections has
+	# those sections preserved...
+	cat >expect <<-\EOF &&
+	branch.dest.key1=value1
+	some.gar.b=age
+	branch.dest.key2=value2
+	EOF
+	cat >config.branch <<\EOF &&
+;; Note the lack of -\EOF above & mixed indenting here. This is
+;; intentional, we are also testing that the formatting of copied
+;; sections is preserved.
+
+;; Comment for source. Tabs
+[branch "source"]
+	;; Comment for the source value
+	key1 = value1
+;; Comment for some.gar. Spaces
+[some "gar"]
+    ;; Comment for the some.gar value
+    b = age
+;; Comment for source, again. Mixed tabs/spaces.
+[branch "source"]
+    ;; Comment for the source value, again
+	key2 = value2
+EOF
+	cat config.branch >>.git/config &&
+	git branch -m source dest &&
+	git config -f .git/config -l | grep -F -e source -e dest -e some.gar >actual &&
+	test_cmp expect actual &&
+
+	# ...and that the comments for those sections are also
+	# preserved.
+	cat config.branch | sed "s/\"source\"/\"dest\"/" >expect &&
+	sed -n -e "/Note the lack/,\$p" .git/config >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'deleting a symref' '
 	git branch target &&
 	git symbolic-ref refs/heads/symref refs/heads/target &&
-- 
2.13.1.611.g7e3b11ae1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 3/3] branch: add a --copy (-c) option to go with --move (-m)
  2017-07-05 22:35 What's cooking in git.git (Jul 2017, #01; Wed, 5) Junio C Hamano
                   ` (3 preceding siblings ...)
  2017-07-05 23:14 ` [PATCH v2 2/3] branch: add test for -m renaming multiple config sections Ævar Arnfjörð Bjarmason
@ 2017-07-05 23:14 ` Ævar Arnfjörð Bjarmason
  4 siblings, 0 replies; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2017-07-05 23:14 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Sahil Dua, Jonathan Nieder, Michael Haggerty,
	Brandon Williams, Ævar Arnfjörð Bjarmason

From: Sahil Dua <sahildua2305@gmail.com>

Add the ability to --copy a branch and its reflog and configuration,
this uses the same underlying machinery as the --move (-m) option
except the reflog and configuration is copied instead of being moved.

This is useful for e.g. copying a topic branch to a new version,
e.g. work to work-2 after submitting the work topic to the list, while
preserving all the tracking info and other configuration that goes
with the branch, and unlike --move keeping the other already-submitted
branch around for reference.

Like --move, when the source branch is the currently checked out
branch the HEAD is moved to the destination branch. In the case of
--move we don't really have a choice (other than remaining on a
detached HEAD) and in order to keep the functionality consistent, we
are doing it in similar way for --copy too.

The most common usage of this feature is expected to be moving to a
new topic branch which is a copy of the current one, in that case
moving to the target branch is what the user wants, and doesn't
unexpectedly behave differently than --move would.

One outstanding caveat of this implementation is that:

    git checkout maint &&
    git checkout master &&
    git branch -c topic &&
    git checkout -

Will check out 'maint' instead of 'master'. This is because the @{-N}
feature (or its -1 shorthand "-") relies on HEAD reflogs created by
the checkout command, so in this case we'll checkout maint instead of
master, as the user might expect. What to do about that is left to a
future change.

Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Sahil Dua <sahildua2305@gmail.com>
---
 Documentation/git-branch.txt |  14 ++-
 builtin/branch.c             |  67 ++++++++++----
 config.c                     | 102 ++++++++++++++++----
 config.h                     |   2 +
 refs.c                       |  11 +++
 refs.h                       |   9 +-
 refs/files-backend.c         |  46 +++++++--
 refs/refs-internal.h         |   4 +
 t/t3200-branch.sh            | 215 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 424 insertions(+), 46 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 81bd0a7b77..94fd89ddc5 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -18,6 +18,7 @@ SYNOPSIS
 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
 'git branch' --unset-upstream [<branchname>]
 'git branch' (-m | -M) [<oldbranch>] <newbranch>
+'git branch' (-c | -C) [<oldbranch>] <newbranch>
 'git branch' (-d | -D) [-r] <branchname>...
 'git branch' --edit-description [<branchname>]
 
@@ -64,6 +65,10 @@ If <oldbranch> had a corresponding reflog, it is renamed to match
 renaming. If <newbranch> exists, -M must be used to force the rename
 to happen.
 
+The `-c` and `-C` options have the exact same semantics as `-m` and
+`-M`, except instead of the branch being renamed it along with its
+config and reflog will be copied to a new name.
+
 With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
 specify more than one branch for deletion.  If the branch currently
 has a reflog then the reflog will also be deleted.
@@ -104,7 +109,7 @@ OPTIONS
 	In combination with `-d` (or `--delete`), allow deleting the
 	branch irrespective of its merged status. In combination with
 	`-m` (or `--move`), allow renaming the branch even if the new
-	branch name already exists.
+	branch name already exists, the same applies for `-c` (or `--copy`).
 
 -m::
 --move::
@@ -113,6 +118,13 @@ OPTIONS
 -M::
 	Shortcut for `--move --force`.
 
+-c::
+--copy::
+	Copy a branch and the corresponding reflog.
+
+-C::
+	Shortcut for `--copy --force`.
+
 --color[=<when>]::
 	Color branches to highlight current, local, and
 	remote-tracking branches.
diff --git a/builtin/branch.c b/builtin/branch.c
index c958e93257..684f2c4f42 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -28,6 +28,7 @@ static const char * const builtin_branch_usage[] = {
 	N_("git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"),
 	N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
 	N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
+	N_("git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"),
 	N_("git branch [<options>] [-r | -a] [--points-at]"),
 	N_("git branch [<options>] [-r | -a] [--format]"),
 	NULL
@@ -450,15 +451,19 @@ static void reject_rebase_or_bisect_branch(const char *target)
 	free_worktrees(worktrees);
 }
 
-static void rename_branch(const char *oldname, const char *newname, int force)
+static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
 {
 	struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
 	struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
 	int recovery = 0;
 	int clobber_head_ok;
 
-	if (!oldname)
-		die(_("cannot rename the current branch while not on any."));
+	if (!oldname) {
+		if (copy)
+			die(_("cannot copy the current branch while not on any."));
+		else
+			die(_("cannot rename the current branch while not on any."));
+	}
 
 	if (strbuf_check_branch_ref(&oldref, oldname)) {
 		/*
@@ -481,17 +486,33 @@ static void rename_branch(const char *oldname, const char *newname, int force)
 
 	reject_rebase_or_bisect_branch(oldref.buf);
 
-	strbuf_addf(&logmsg, "Branch: renamed %s to %s",
-		 oldref.buf, newref.buf);
+	if (copy)
+		strbuf_addf(&logmsg, "Branch: copied %s to %s",
+			    oldref.buf, newref.buf);
+	else
+		strbuf_addf(&logmsg, "Branch: renamed %s to %s",
+			    oldref.buf, newref.buf);
 
-	if (rename_ref(oldref.buf, newref.buf, logmsg.buf))
+	if (!copy && rename_ref(oldref.buf, newref.buf, logmsg.buf))
 		die(_("Branch rename failed"));
+	if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
+		die(_("Branch copy failed"));
 
-	if (recovery)
-		warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11);
+	if (recovery) {
+		if (copy)
+			warning(_("Copied a misnamed branch '%s' away"),
+				oldref.buf + 11);
+		else
+			warning(_("Renamed a misnamed branch '%s' away"),
+				oldref.buf + 11);
+	}
 
-	if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
-		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
+	if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf)) {
+		if (copy)
+			die(_("Branch copied to %s, but HEAD is not updated!"), newname);
+		else
+			die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
+	}
 
 	strbuf_release(&logmsg);
 
@@ -499,8 +520,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)
 	strbuf_release(&oldref);
 	strbuf_addf(&newsection, "branch.%s", newref.buf + 11);
 	strbuf_release(&newref);
-	if (git_config_rename_section(oldsection.buf, newsection.buf) < 0)
+	if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
 		die(_("Branch is renamed, but update of config-file failed"));
+	if (copy && strcmp(oldname, newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
+		die(_("Branch is copied, but update of config-file failed"));
 	strbuf_release(&oldsection);
 	strbuf_release(&newsection);
 }
@@ -538,7 +561,7 @@ static int edit_branch_description(const char *branch_name)
 
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
-	int delete = 0, rename = 0, force = 0, list = 0;
+	int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
 	int reflog = 0, edit_description = 0;
 	int quiet = 0, unset_upstream = 0;
 	const char *new_upstream = NULL;
@@ -575,6 +598,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
 		OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
 		OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
+		OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
+		OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
 		OPT_BOOL(0, "list", &list, N_("list branch names")),
 		OPT_BOOL('l', "create-reflog", &reflog, N_("create the branch's reflog")),
 		OPT_BOOL(0, "edit-description", &edit_description,
@@ -618,14 +643,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 			     0);
 
-	if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
+	if (!delete && !rename && !copy && !edit_description && !new_upstream && !unset_upstream && argc == 0)
 		list = 1;
 
 	if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr ||
 	    filter.no_commit)
 		list = 1;
 
-	if (!!delete + !!rename + !!new_upstream +
+	if (!!delete + !!rename + !!copy + !!new_upstream +
 	    list + unset_upstream > 1)
 		usage_with_options(builtin_branch_usage, options);
 
@@ -643,6 +668,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	if (force) {
 		delete *= 2;
 		rename *= 2;
+		copy *= 2;
 	}
 
 	if (delete) {
@@ -697,13 +723,22 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 		if (edit_branch_description(branch_name))
 			return 1;
+	} else if (copy) {
+		if (!argc)
+			die(_("branch name required"));
+		else if (argc == 1)
+			copy_or_rename_branch(head, argv[0], 1, copy > 1);
+		else if (argc == 2)
+			copy_or_rename_branch(argv[0], argv[1], 1, copy > 1);
+		else
+			die(_("too many branches for a copy operation"));
 	} else if (rename) {
 		if (!argc)
 			die(_("branch name required"));
 		else if (argc == 1)
-			rename_branch(head, argv[0], rename > 1);
+			copy_or_rename_branch(head, argv[0], 0, rename > 1);
 		else if (argc == 2)
-			rename_branch(argv[0], argv[1], rename > 1);
+			copy_or_rename_branch(argv[0], argv[1], 0, rename > 1);
 		else
 			die(_("too many branches for a rename operation"));
 	} else if (new_upstream) {
diff --git a/config.c b/config.c
index b7afb5941b..9ee3fcafcf 100644
--- a/config.c
+++ b/config.c
@@ -2713,8 +2713,8 @@ static int section_name_is_ok(const char *name)
 }
 
 /* if new_name == NULL, the section is removed instead */
-int git_config_rename_section_in_file(const char *config_filename,
-				      const char *old_name, const char *new_name)
+static int git_config_copy_or_rename_section_in_file(const char *config_filename,
+				      const char *old_name, const char *new_name, int copy)
 {
 	int ret = 0, remove = 0;
 	char *filename_buf = NULL;
@@ -2723,6 +2723,7 @@ int git_config_rename_section_in_file(const char *config_filename,
 	char buf[1024];
 	FILE *config_file = NULL;
 	struct stat st;
+	struct strbuf copystr = STRBUF_INIT;
 
 	if (new_name && !section_name_is_ok(new_name)) {
 		ret = error("invalid section name: %s", new_name);
@@ -2761,12 +2762,30 @@ int git_config_rename_section_in_file(const char *config_filename,
 	while (fgets(buf, sizeof(buf), config_file)) {
 		int i;
 		int length;
+		int is_section = 0;
 		char *output = buf;
 		for (i = 0; buf[i] && isspace(buf[i]); i++)
 			; /* do nothing */
 		if (buf[i] == '[') {
 			/* it's a section */
-			int offset = section_name_match(&buf[i], old_name);
+			int offset;
+			is_section = 1;
+
+			/*
+			 * When encountering a new section under -c we
+			 * need to flush out any section we're already
+			 * coping and begin anew. There might be
+			 * multiple [branch "$name"] sections.
+			 */
+			if (copystr.len > 0) {
+				if (write_in_full(out_fd, copystr.buf, copystr.len) != copystr.len) {
+					ret = write_error(get_lock_file_path(lock));
+					goto out;
+				}
+				strbuf_reset(&copystr);
+			}
+
+			offset = section_name_match(&buf[i], old_name);
 			if (offset > 0) {
 				ret++;
 				if (new_name == NULL) {
@@ -2774,25 +2793,30 @@ int git_config_rename_section_in_file(const char *config_filename,
 					continue;
 				}
 				store.baselen = strlen(new_name);
-				if (!store_write_section(out_fd, new_name)) {
-					ret = write_error(get_lock_file_path(lock));
-					goto out;
-				}
-				/*
-				 * We wrote out the new section, with
-				 * a newline, now skip the old
-				 * section's length
-				 */
-				output += offset + i;
-				if (strlen(output) > 0) {
+				if (!copy) {
+					if (!store_write_section(out_fd, new_name)) {
+						ret = write_error(get_lock_file_path(lock));
+						goto out;
+					}
+
 					/*
-					 * More content means there's
-					 * a declaration to put on the
-					 * next line; indent with a
-					 * tab
+					 * We wrote out the new section, with
+					 * a newline, now skip the old
+					 * section's length
 					 */
-					output -= 1;
-					output[0] = '\t';
+					output += offset + i;
+					if (strlen(output) > 0) {
+						/*
+						 * More content means there's
+						 * a declaration to put on the
+						 * next line; indent with a
+						 * tab
+						 */
+						output -= 1;
+						output[0] = '\t';
+					}
+				} else {
+					copystr = store_create_section(new_name);
 				}
 			}
 			remove = 0;
@@ -2800,11 +2824,30 @@ int git_config_rename_section_in_file(const char *config_filename,
 		if (remove)
 			continue;
 		length = strlen(output);
+
+		if (!is_section && copystr.len > 0) {
+			strbuf_add(&copystr, output, length);
+		}
+
 		if (write_in_full(out_fd, output, length) != length) {
 			ret = write_error(get_lock_file_path(lock));
 			goto out;
 		}
 	}
+
+	/*
+	 * Copy a trailing section at the end of the config, won't be
+	 * flushed by the usual "flush because we have a new section
+	 * logic in the loop above.
+	 */
+	if (copystr.len > 0) {
+		if (write_in_full(out_fd, copystr.buf, copystr.len) != copystr.len) {
+			ret = write_error(get_lock_file_path(lock));
+			goto out;
+		}
+		strbuf_reset(&copystr);
+	}
+
 	fclose(config_file);
 	config_file = NULL;
 commit_and_out:
@@ -2820,11 +2863,30 @@ int git_config_rename_section_in_file(const char *config_filename,
 	return ret;
 }
 
+int git_config_rename_section_in_file(const char *config_filename,
+				      const char *old_name, const char *new_name)
+{
+	return git_config_copy_or_rename_section_in_file(config_filename,
+					 old_name, new_name, 0);
+}
+
 int git_config_rename_section(const char *old_name, const char *new_name)
 {
 	return git_config_rename_section_in_file(NULL, old_name, new_name);
 }
 
+int git_config_copy_section_in_file(const char *config_filename,
+				      const char *old_name, const char *new_name)
+{
+	return git_config_copy_or_rename_section_in_file(config_filename,
+					 old_name, new_name, 1);
+}
+
+int git_config_copy_section(const char *old_name, const char *new_name)
+{
+	return git_config_copy_section_in_file(NULL, old_name, new_name);
+}
+
 /*
  * Call this to report error for your variable that should not
  * get a boolean value (i.e. "[my] var" means "true").
diff --git a/config.h b/config.h
index 0352da117b..e9bdecbf88 100644
--- a/config.h
+++ b/config.h
@@ -71,6 +71,8 @@ extern int git_config_set_multivar_in_file_gently(const char *, const char *, co
 extern void git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
 extern int git_config_rename_section_in_file(const char *, const char *, const char *);
+extern int git_config_copy_section(const char *, const char *);
+extern int git_config_copy_section_in_file(const char *, const char *, const char *);
 extern const char *git_etc_gitconfig(void);
 extern int git_env_bool(const char *, int);
 extern unsigned long git_env_ulong(const char *, unsigned long);
diff --git a/refs.c b/refs.c
index 88658ba769..8a334a2ff0 100644
--- a/refs.c
+++ b/refs.c
@@ -2045,3 +2045,14 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 {
 	return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg);
 }
+
+int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
+		    const char *newref, const char *logmsg)
+{
+	return refs->be->copy_ref(refs, oldref, newref, logmsg);
+}
+
+int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
+{
+	return refs_copy_existing_ref(get_main_ref_store(), oldref, newref, logmsg);
+}
diff --git a/refs.h b/refs.h
index 6daa78eb50..80da9fe389 100644
--- a/refs.h
+++ b/refs.h
@@ -443,7 +443,14 @@ char *shorten_unambiguous_ref(const char *refname, int strict);
 /** rename ref, return 0 on success **/
 int refs_rename_ref(struct ref_store *refs, const char *oldref,
 		    const char *newref, const char *logmsg);
-int rename_ref(const char *oldref, const char *newref, const char *logmsg);
+int rename_ref(const char *oldref, const char *newref,
+			const char *logmsg);
+
+/** copy ref, return 0 on success **/
+int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
+		    const char *newref, const char *logmsg);
+int copy_existing_ref(const char *oldref, const char *newref,
+			const char *logmsg);
 
 int refs_create_symref(struct ref_store *refs, const char *refname,
 		       const char *target, const char *logmsg);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 0404f2c233..000362b9d8 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1748,9 +1748,9 @@ static int commit_ref_update(struct files_ref_store *refs,
 			     const struct object_id *oid, const char *logmsg,
 			     struct strbuf *err);
 
-static int files_rename_ref(struct ref_store *ref_store,
+static int files_copy_or_rename_ref(struct ref_store *ref_store,
 			    const char *oldrefname, const char *newrefname,
-			    const char *logmsg)
+			    const char *logmsg, int copy)
 {
 	struct files_ref_store *refs =
 		files_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
@@ -1782,8 +1782,12 @@ static int files_rename_ref(struct ref_store *ref_store,
 	}
 
 	if (flag & REF_ISSYMREF) {
-		ret = error("refname %s is a symbolic ref, renaming it is not supported",
-			    oldrefname);
+		if (copy)
+			ret = error("refname %s is a symbolic ref, copying it is not supported",
+				    oldrefname);
+		else
+			ret = error("refname %s is a symbolic ref, renaming it is not supported",
+				    oldrefname);
 		goto out;
 	}
 	if (!refs_rename_ref_available(&refs->base, oldrefname, newrefname)) {
@@ -1791,13 +1795,19 @@ static int files_rename_ref(struct ref_store *ref_store,
 		goto out;
 	}
 
-	if (log && rename(sb_oldref.buf, tmp_renamed_log.buf)) {
+	if (!copy && log && rename(sb_oldref.buf, tmp_renamed_log.buf)) {
 		ret = error("unable to move logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
 			    oldrefname, strerror(errno));
 		goto out;
 	}
 
-	if (refs_delete_ref(&refs->base, logmsg, oldrefname,
+	if (copy && log && copy_file(tmp_renamed_log.buf, sb_oldref.buf, 0644)) {
+		ret = error("unable to copy logfile logs/%s to logs/"TMP_RENAMED_LOG": %s",
+			    oldrefname, strerror(errno));
+		goto out;
+	}
+
+	if (!copy && refs_delete_ref(&refs->base, logmsg, oldrefname,
 			    orig_oid.hash, REF_NODEREF)) {
 		error("unable to delete old %s", oldrefname);
 		goto rollback;
@@ -1810,7 +1820,7 @@ static int files_rename_ref(struct ref_store *ref_store,
 	 * the safety anyway; we want to delete the reference whatever
 	 * its current value.
 	 */
-	if (!refs_read_ref_full(&refs->base, newrefname,
+	if (!copy && !refs_read_ref_full(&refs->base, newrefname,
 				RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
 				oid.hash, NULL) &&
 	    refs_delete_ref(&refs->base, NULL, newrefname,
@@ -1841,7 +1851,10 @@ static int files_rename_ref(struct ref_store *ref_store,
 	lock = lock_ref_sha1_basic(refs, newrefname, NULL, NULL, NULL,
 				   REF_NODEREF, NULL, &err);
 	if (!lock) {
-		error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
+		if (copy)
+			error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf);
+		else
+			error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
 		strbuf_release(&err);
 		goto rollback;
 	}
@@ -1892,6 +1905,22 @@ static int files_rename_ref(struct ref_store *ref_store,
 	return ret;
 }
 
+static int files_rename_ref(struct ref_store *ref_store,
+			    const char *oldrefname, const char *newrefname,
+			    const char *logmsg)
+{
+	return files_copy_or_rename_ref(ref_store, oldrefname,
+				 newrefname, logmsg, 0);
+}
+
+static int files_copy_ref(struct ref_store *ref_store,
+			    const char *oldrefname, const char *newrefname,
+			    const char *logmsg)
+{
+	return files_copy_or_rename_ref(ref_store, oldrefname,
+				 newrefname, logmsg, 1);
+}
+
 static int close_ref(struct ref_lock *lock)
 {
 	if (close_lock_file(lock->lk))
@@ -3397,6 +3426,7 @@ struct ref_storage_be refs_be_files = {
 	files_create_symref,
 	files_delete_refs,
 	files_rename_ref,
+	files_copy_ref,
 
 	files_ref_iterator_begin,
 	files_read_raw_ref,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 192f9f85c9..3c51194edb 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -543,6 +543,9 @@ typedef int delete_refs_fn(struct ref_store *ref_store, const char *msg,
 typedef int rename_ref_fn(struct ref_store *ref_store,
 			  const char *oldref, const char *newref,
 			  const char *logmsg);
+typedef int copy_ref_fn(struct ref_store *ref_store,
+			  const char *oldref, const char *newref,
+			  const char *logmsg);
 
 /*
  * Iterate over the references in `ref_store` whose names start with
@@ -641,6 +644,7 @@ struct ref_storage_be {
 	create_symref_fn *create_symref;
 	delete_refs_fn *delete_refs;
 	rename_ref_fn *rename_ref;
+	copy_ref_fn *copy_ref;
 
 	ref_iterator_begin_fn *iterator_begin;
 	read_raw_ref_fn *read_raw_ref;
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 596fbc8483..5402933877 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -399,6 +399,221 @@ EOF
 	test_cmp expect actual
 '
 
+test_expect_success 'git branch -c dumps usage' '
+	test_expect_code 128 git branch -c 2>err &&
+	test_i18ngrep "branch name required" err
+'
+
+test_expect_success 'git branch --copy dumps usage' '
+	test_expect_code 128 git branch --copy 2>err &&
+	test_i18ngrep "branch name required" err
+'
+
+test_expect_success 'git branch -c d e should work' '
+	git branch -l d &&
+	git reflog exists refs/heads/d &&
+	git config branch.d.dummy Hello &&
+	git branch -c d e &&
+	git reflog exists refs/heads/d &&
+	git reflog exists refs/heads/e &&
+	echo Hello >expect &&
+	git config branch.e.dummy >actual &&
+	test_cmp expect actual &&
+	echo Hello >expect &&
+	git config branch.d.dummy >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git branch --copy is a synonym for -c' '
+	git branch -l copy &&
+	git reflog exists refs/heads/copy &&
+	git config branch.copy.dummy Hello &&
+	git branch --copy copy copy-to &&
+	git reflog exists refs/heads/copy &&
+	git reflog exists refs/heads/copy-to &&
+	echo Hello >expect &&
+	git config branch.copy.dummy >actual &&
+	test_cmp expect actual &&
+	echo Hello >expect &&
+	git config branch.copy-to.dummy >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
+	git checkout -b ee &&
+	git reflog exists refs/heads/ee &&
+	git config branch.ee.dummy Hello &&
+	git branch -c ee ef &&
+	git reflog exists refs/heads/ee &&
+	git reflog exists refs/heads/ef &&
+	test $(git config branch.ee.dummy) = Hello &&
+	test $(git config branch.ef.dummy) = Hello &&
+	test $(git rev-parse --abbrev-ref HEAD) = ef
+'
+
+test_expect_success 'git branch -c f/f g/g should work' '
+	git branch -l f/f &&
+	git reflog exists refs/heads/f/f &&
+	git config branch.f/f.dummy Hello &&
+	git branch -c f/f g/g &&
+	git reflog exists refs/heads/f/f &&
+	git reflog exists refs/heads/g/g &&
+	test $(git config branch.f/f.dummy) = Hello &&
+	test $(git config branch.g/g.dummy) = Hello
+'
+
+test_expect_success 'git branch -c m2 m2 should work' '
+	git branch -l m2 &&
+	git reflog exists refs/heads/m2 &&
+	git config branch.m2.dummy Hello &&
+	git branch -c m2 m2 &&
+	git reflog exists refs/heads/m2 &&
+	test $(git config branch.m2.dummy) = Hello
+'
+
+test_expect_success 'git branch -c zz zz/zz should fail' '
+	git branch -l zz &&
+	git reflog exists refs/heads/zz &&
+	test_must_fail git branch -c zz zz/zz
+'
+
+test_expect_success 'git branch -c b/b b should fail' '
+	git branch -l b/b &&
+	test_must_fail git branch -c b/b b
+'
+
+test_expect_success 'git branch -C o/q o/p should work when o/p exists' '
+	git branch -l o/q &&
+	git reflog exists refs/heads/o/q &&
+	git reflog exists refs/heads/o/p &&
+	git branch -C o/q o/p
+'
+
+test_expect_success 'git branch -c -f o/q o/p should work when o/p exists' '
+	git reflog exists refs/heads/o/q &&
+	git reflog exists refs/heads/o/p &&
+	git branch -c -f o/q o/p
+'
+
+test_expect_success 'git branch -c qq rr/qq should fail when r exists' '
+	git branch qq &&
+	git branch rr &&
+	test_must_fail git branch -c qq rr/qq
+'
+
+test_expect_success 'git branch -C b1 b2 should fail when b2 is checked out' '
+	git branch b1 &&
+	git checkout -b b2 &&
+	test_must_fail git branch -C b1 b2
+'
+
+test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out' '
+	git checkout -b c1 &&
+	git branch c2 &&
+	git branch -C c1 c2 &&
+	test $(git rev-parse --abbrev-ref HEAD) = c2
+'
+
+test_expect_success 'git branch -C c1 c2 should add entries to .git/logs/HEAD' '
+	msg="Branch: copied refs/heads/c1 to refs/heads/c2" &&
+	grep "$msg$" .git/logs/HEAD
+'
+
+test_expect_success 'git branch -C master should work when master is checked out' '
+	git checkout master &&
+	git branch -C master
+'
+
+test_expect_success 'git branch -C master master should work when master is checked out' '
+	git checkout master &&
+	git branch -C master master
+'
+
+test_expect_success 'git branch -C master5 master5 should work when master is checked out' '
+	git checkout master &&
+	git branch master5 &&
+	git branch -C master5 master5
+'
+
+test_expect_success 'git branch -C ab cd should overwrite existing config for cd' '
+	git branch -l cd &&
+	git reflog exists refs/heads/cd &&
+	git config branch.cd.dummy CD &&
+	git branch -l ab &&
+	git reflog exists refs/heads/ab &&
+	git config branch.ab.dummy AB &&
+	git branch -C ab cd &&
+	git reflog exists refs/heads/ab &&
+	git reflog exists refs/heads/cd &&
+	test $(git config branch.ab.dummy) = AB &&
+	test $(git config branch.cd.dummy) = AB
+'
+
+test_expect_success 'git branch -c correctly copies multiple config sections' '
+	FOO=1 &&
+	export FOO &&
+	test_when_finished "git checkout master" &&
+	git checkout -b source2 master &&
+
+	# Assert that a config file with multiple config sections has
+	# those sections preserved...
+	cat >expect <<-\EOF &&
+	branch.source2.key1=value1
+	branch.dest2.key1=value1
+	more.gar.b=age
+	branch.source2.key2=value2
+	branch.dest2.key2=value2
+	EOF
+	cat >config.branch <<\EOF &&
+;; Note the lack of -\EOF above & mixed indenting here. This is
+;; intentional, we are also testing that the formatting of copied
+;; sections is preserved.
+
+;; Comment for source2. Tabs
+[branch "source2"]
+	;; Comment for the source2 value
+	key1 = value1
+;; Comment for more.gar. Spaces
+[more "gar"]
+    ;; Comment for the more.gar value
+    b = age
+;; Comment for source2, again. Mixed tabs/spaces.
+[branch "source2"]
+    ;; Comment for the source2 value, again
+	key2 = value2
+EOF
+	cat config.branch >>.git/config &&
+	git branch -c source2 dest2 &&
+	git config -f .git/config -l | grep -F -e source2 -e dest2 -e more.gar >actual &&
+	test_cmp expect actual &&
+
+	# ...and that the comments and formatting for those sections
+	# is also preserved.
+	cat >expect <<\EOF &&
+;; Comment for source2. Tabs
+[branch "source2"]
+	;; Comment for the source2 value
+	key1 = value1
+;; Comment for more.gar. Spaces
+[branch "dest2"]
+	;; Comment for the source2 value
+	key1 = value1
+;; Comment for more.gar. Spaces
+[more "gar"]
+    ;; Comment for the more.gar value
+    b = age
+;; Comment for source2, again. Mixed tabs/spaces.
+[branch "source2"]
+    ;; Comment for the source2 value, again
+	key2 = value2
+[branch "dest2"]
+    ;; Comment for the source2 value, again
+	key2 = value2
+EOF
+	sed -n -e "/Comment for source2/,\$p" .git/config >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'deleting a symref' '
 	git branch target &&
 	git symbolic-ref refs/heads/symref refs/heads/target &&
-- 
2.13.1.611.g7e3b11ae1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 0/3] branch: add a --copy to go with --move
  2017-07-05 23:14 ` [PATCH v2 0/3] branch: add a --copy to go with --move Ævar Arnfjörð Bjarmason
@ 2017-07-06  0:37   ` Junio C Hamano
  2017-09-22  4:57     ` [PATCH 4/3] branch: fix "copy" to never touch HEAD Junio C Hamano
  0 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2017-07-06  0:37 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Sahil Dua, Jonathan Nieder, Michael Haggerty,
	Brandon Williams

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Even though this modifies some of the same files as
> mh/packed-ref-store it looks to me like this doesn't conflict with
> that topic in any meaningful way, but I may be missing something. I
> can't get a merge between this & gitster/mh/packed-ref-store
> compiling,...

That is because each ref backend is required to implement a new
method by that topic.  The following patch needs to be squashed in
while merging the two topics, making the resulting commit an evil
merge.

FWIW, the result of applying these three patches on 'master' and
merging the result to a commit on 'pu' that is just before the merge
of previous round of the same topic, with the attached fix-up, exactly
matches the commit on 'pu' that merges the previous round, iow, I see
there is no meaningful change (perhaps other than log message?  I
didn't check) in this new round.

Note that I am not complaining that this new round does not bring
any improvements---I am not commending that you didn't screw up
while rebasing to a new commit, either ;-).

diff --git b/refs/packed-backend.c a/refs/packed-backend.c
index dc09012300..96f9141656 100644
--- b/refs/packed-backend.c
+++ a/refs/packed-backend.c
@@ -794,6 +794,13 @@ static int packed_rename_ref(struct ref_store *ref_store,
 	die("BUG: packed reference store does not support renaming references");
 }
 
+static int packed_copy_ref(struct ref_store *ref_store,
+			   const char *oldrefname, const char *newrefname,
+			   const char *logmsg)
+{
+	die("BUG: packed reference store does not support copying references");
+}
+
 static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store)
 {
 	return empty_ref_iterator_begin();
@@ -859,6 +866,7 @@ struct ref_storage_be refs_be_packed = {
 	packed_create_symref,
 	packed_delete_refs,
 	packed_rename_ref,
+	packed_copy_ref,
 
 	packed_ref_iterator_begin,
 	packed_read_raw_ref,


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: What's cooking in git.git (Jul 2017, #01; Wed, 5)
  2017-07-05 23:06 ` Stefan Beller
@ 2017-07-07  2:13   ` Junio C Hamano
  2017-07-10 17:27     ` Stefan Beller
  0 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2017-07-07  2:13 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git@vger.kernel.org

Stefan Beller <sbeller@google.com> writes:

> Speaking of submodules, It's not just features, but I also send bug fixes. ;)
> https://public-inbox.org/git/20170630003851.17288-1-sbeller@google.com/
> (That patch is not related to this series, except for working in the submodule
> area, but I consider that patch more important than e.g. this series.)

I did not see the patch as fixing a bug, though.  

I do agree that overwriting the branch tips in the submodule
repositories, possibly rewinding and discarding user's work done on
the local branches, is indeed a problem.  It however is unclear why
detaching HEAD is a good solution to solve that problem.

After all, there must have been a reason why the user had checked
out a branch and had pointed it at a specific commit (presumably,
so that further work would be done while on the branch, to make it
easier and safer to eventually push the result back to the upstream
of the submodule's project).  So another solution that seems equally
viable, if not even more so, could be to fail the recursive checkout
saying why the checkout cannot be done, just like we fail a checkout
when a local change interferes with updating the contents in the
working tree and the index with an error message explaining which
paths are problematic.

I am *not* saying which one among the above two is better; I am not
even saying that there could be only these two possible solutions.
I just found the posted patch unsatisfactory because it did not make
it clear why the chosen solution is a good one.

Perhaps I misread the description; but that would mean the
description was prone to be misread and has room for improvement ;-)





^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: What's cooking in git.git (Jul 2017, #01; Wed, 5)
  2017-07-07  2:13   ` Junio C Hamano
@ 2017-07-10 17:27     ` Stefan Beller
  0 siblings, 0 replies; 14+ messages in thread
From: Stefan Beller @ 2017-07-10 17:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org

On Thu, Jul 6, 2017 at 7:13 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Stefan Beller <sbeller@google.com> writes:
>
>> Speaking of submodules, It's not just features, but I also send bug fixes. ;)
>> https://public-inbox.org/git/20170630003851.17288-1-sbeller@google.com/
>> (That patch is not related to this series, except for working in the submodule
>> area, but I consider that patch more important than e.g. this series.)
>
> I did not see the patch as fixing a bug, though.
>
> I do agree that overwriting the branch tips in the submodule
> repositories, possibly rewinding and discarding user's work done on
> the local branches, is indeed a problem.  It however is unclear why
> detaching HEAD is a good solution to solve that problem.

I am not saying detaching a HEAD is a good solution, but I am saying
it is a better solution than corrupting the submodule branch, such
that commits are lost in the submodule, only to be recorvered via the
reflog.

> After all, there must have been a reason why the user had checked
> out a branch and had pointed it at a specific commit (presumably,
> so that further work would be done while on the branch, to make it
> easier and safer to eventually push the result back to the upstream
> of the submodule's project).  So another solution that seems equally
> viable, if not even more so, could be to fail the recursive checkout
> saying why the checkout cannot be done, just like we fail a checkout
> when a local change interferes with updating the contents in the
> working tree and the index with an error message explaining which
> paths are problematic.

That seems like a better model to me for now.

> I am *not* saying which one among the above two is better; I am not
> even saying that there could be only these two possible solutions.
> I just found the posted patch unsatisfactory because it did not make
> it clear why the chosen solution is a good one.

ok. My long term plan is to introduce another type of symbolic ref,
which references a gitlink in another repository, such that the submodule
can have a clear distinction between "follows the superproject",
"has its own authoritative branch" and "its detached HEAD can mean
anything, e.g. historical submodule behavior"

> Perhaps I misread the description; but that would mean the
> description was prone to be misread and has room for improvement ;-)

ok.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 4/3] branch: fix "copy" to never touch HEAD
  2017-07-06  0:37   ` Junio C Hamano
@ 2017-09-22  4:57     ` Junio C Hamano
  2017-09-22 16:33       ` Brandon Williams
  2017-09-26 21:39       ` Ævar Arnfjörð Bjarmason
  0 siblings, 2 replies; 14+ messages in thread
From: Junio C Hamano @ 2017-09-22  4:57 UTC (permalink / raw)
  To: Sahil Dua
  Cc: Ævar Arnfjörð Bjarmason, git, Jonathan Nieder,
	Michael Haggerty, Brandon Williams

When creating a new branch B by copying the branch A that happens to
be the current branch, it also updates HEAD to point at the new
branch.  It probably was made this way because "git branch -c A B"
piggybacked its implementation on "git branch -m A B",

This does not match the usual expectation.  If I were sitting on a
blue chair, and somebody comes and repaints it to red, I would
accept ending up sitting on a chair that is now red (I am also OK to
stand, instead, as there no longer is my favourite blue chair).  But
if somebody creates a new red chair, modelling it after the blue
chair I am sitting on, I do not expect to be booted off of the blue
chair and ending up on sitting on the new red one.

Let's fix this before it hits 'next'.  Those who want to create a
new branch and switch to it can do "git checkout B" after doing a
"git branch -c B", and if that operation is so useful and deserves a
short-hand way to do so, perhaps extend "git checkout -b B" to copy
configurations while creating the new branch B.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * Let's send an updated one as a follow-up to the discussion thread
   that it is a follow-up to.  The patch in this message is the same
   as the one I previously sent; the proposed log message has been
   updated somewhat.

 builtin/branch.c  |  9 +++------
 t/t3200-branch.sh | 10 +++++-----
 2 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 89f64f4123..e2e3692838 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -506,12 +506,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 				oldref.buf + 11);
 	}
 
-	if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf)) {
-		if (copy)
-			die(_("Branch copied to %s, but HEAD is not updated!"), newname);
-		else
-			die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
-	}
+	if (!copy &&
+	    replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
+		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
 
 	strbuf_release(&logmsg);
 
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 5d03ad16f6..be9b3784c6 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -422,7 +422,7 @@ test_expect_success 'git branch --copy is a synonym for -c' '
 	test_cmp expect actual
 '
 
-test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
+test_expect_success 'git branch -c ee ef should copy to create branch ef' '
 	git checkout -b ee &&
 	git reflog exists refs/heads/ee &&
 	git config branch.ee.dummy Hello &&
@@ -431,7 +431,7 @@ test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
 	git reflog exists refs/heads/ef &&
 	test $(git config branch.ee.dummy) = Hello &&
 	test $(git config branch.ef.dummy) = Hello &&
-	test $(git rev-parse --abbrev-ref HEAD) = ef
+	test $(git rev-parse --abbrev-ref HEAD) = ee
 '
 
 test_expect_success 'git branch -c f/f g/g should work' '
@@ -494,12 +494,12 @@ test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out'
 	git checkout -b c1 &&
 	git branch c2 &&
 	git branch -C c1 c2 &&
-	test $(git rev-parse --abbrev-ref HEAD) = c2
+	test $(git rev-parse --abbrev-ref HEAD) = c1
 '
 
-test_expect_success 'git branch -C c1 c2 should add entries to .git/logs/HEAD' '
+test_expect_success 'git branch -C c1 c2 should never touch HEAD' '
 	msg="Branch: copied refs/heads/c1 to refs/heads/c2" &&
-	grep "$msg$" .git/logs/HEAD
+	! grep "$msg$" .git/logs/HEAD
 '
 
 test_expect_success 'git branch -C master should work when master is checked out' '
-- 
2.14.1-929-g25eae544e9


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/3] branch: fix "copy" to never touch HEAD
  2017-09-22  4:57     ` [PATCH 4/3] branch: fix "copy" to never touch HEAD Junio C Hamano
@ 2017-09-22 16:33       ` Brandon Williams
  2017-09-26 21:39       ` Ævar Arnfjörð Bjarmason
  1 sibling, 0 replies; 14+ messages in thread
From: Brandon Williams @ 2017-09-22 16:33 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Sahil Dua, Ævar Arnfjörð Bjarmason, git,
	Jonathan Nieder, Michael Haggerty

On 09/22, Junio C Hamano wrote:
> When creating a new branch B by copying the branch A that happens to
> be the current branch, it also updates HEAD to point at the new
> branch.  It probably was made this way because "git branch -c A B"
> piggybacked its implementation on "git branch -m A B",
> 
> This does not match the usual expectation.  If I were sitting on a
> blue chair, and somebody comes and repaints it to red, I would
> accept ending up sitting on a chair that is now red (I am also OK to
> stand, instead, as there no longer is my favourite blue chair).  But
> if somebody creates a new red chair, modelling it after the blue
> chair I am sitting on, I do not expect to be booted off of the blue
> chair and ending up on sitting on the new red one.
> 
> Let's fix this before it hits 'next'.  Those who want to create a
> new branch and switch to it can do "git checkout B" after doing a
> "git branch -c B", and if that operation is so useful and deserves a
> short-hand way to do so, perhaps extend "git checkout -b B" to copy
> configurations while creating the new branch B.
> 
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
> 
>  * Let's send an updated one as a follow-up to the discussion thread
>    that it is a follow-up to.  The patch in this message is the same
>    as the one I previously sent; the proposed log message has been
>    updated somewhat.
> 
>  builtin/branch.c  |  9 +++------
>  t/t3200-branch.sh | 10 +++++-----
>  2 files changed, 8 insertions(+), 11 deletions(-)
> 
> diff --git a/builtin/branch.c b/builtin/branch.c
> index 89f64f4123..e2e3692838 100644
> --- a/builtin/branch.c
> +++ b/builtin/branch.c
> @@ -506,12 +506,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
>  				oldref.buf + 11);
>  	}
>  
> -	if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf)) {
> -		if (copy)
> -			die(_("Branch copied to %s, but HEAD is not updated!"), newname);
> -		else
> -			die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
> -	}
> +	if (!copy &&
> +	    replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
> +		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
>  
>  	strbuf_release(&logmsg);
>  
> diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
> index 5d03ad16f6..be9b3784c6 100755
> --- a/t/t3200-branch.sh
> +++ b/t/t3200-branch.sh
> @@ -422,7 +422,7 @@ test_expect_success 'git branch --copy is a synonym for -c' '
>  	test_cmp expect actual
>  '
>  
> -test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
> +test_expect_success 'git branch -c ee ef should copy to create branch ef' '

The new wording seems to be missing something.  Maybe it should read:
  
  'git branch -c ee ef should copy branch ee to create branch ef'

>  	git checkout -b ee &&
>  	git reflog exists refs/heads/ee &&
>  	git config branch.ee.dummy Hello &&
> @@ -431,7 +431,7 @@ test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
>  	git reflog exists refs/heads/ef &&
>  	test $(git config branch.ee.dummy) = Hello &&
>  	test $(git config branch.ef.dummy) = Hello &&
> -	test $(git rev-parse --abbrev-ref HEAD) = ef
> +	test $(git rev-parse --abbrev-ref HEAD) = ee
>  '
>  
>  test_expect_success 'git branch -c f/f g/g should work' '
> @@ -494,12 +494,12 @@ test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out'
>  	git checkout -b c1 &&
>  	git branch c2 &&
>  	git branch -C c1 c2 &&
> -	test $(git rev-parse --abbrev-ref HEAD) = c2
> +	test $(git rev-parse --abbrev-ref HEAD) = c1
>  '
>  
> -test_expect_success 'git branch -C c1 c2 should add entries to .git/logs/HEAD' '
> +test_expect_success 'git branch -C c1 c2 should never touch HEAD' '
>  	msg="Branch: copied refs/heads/c1 to refs/heads/c2" &&
> -	grep "$msg$" .git/logs/HEAD
> +	! grep "$msg$" .git/logs/HEAD
>  '
>  
>  test_expect_success 'git branch -C master should work when master is checked out' '
> -- 
> 2.14.1-929-g25eae544e9
> 

The rest of the patch lgtm.  I agree that this is probably a better UI
than without this patch.  Especially since the vanilla behavior of git
branch is to create a new branch without moving you to that new branch.

-- 
Brandon Williams

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/3] branch: fix "copy" to never touch HEAD
  2017-09-22  4:57     ` [PATCH 4/3] branch: fix "copy" to never touch HEAD Junio C Hamano
  2017-09-22 16:33       ` Brandon Williams
@ 2017-09-26 21:39       ` Ævar Arnfjörð Bjarmason
  2017-09-27  2:02         ` Junio C Hamano
  1 sibling, 1 reply; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2017-09-26 21:39 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Sahil Dua, git, Jonathan Nieder, Michael Haggerty,
	Brandon Williams


On Fri, Sep 22 2017, Junio C. Hamano jotted:

> When creating a new branch B by copying the branch A that happens to
> be the current branch, it also updates HEAD to point at the new
> branch.  It probably was made this way because "git branch -c A B"
> piggybacked its implementation on "git branch -m A B",
>
> This does not match the usual expectation.  If I were sitting on a
> blue chair, and somebody comes and repaints it to red, I would
> accept ending up sitting on a chair that is now red (I am also OK to
> stand, instead, as there no longer is my favourite blue chair).  But
> if somebody creates a new red chair, modelling it after the blue
> chair I am sitting on, I do not expect to be booted off of the blue
> chair and ending up on sitting on the new red one.
>
> Let's fix this before it hits 'next'.  Those who want to create a
> new branch and switch to it can do "git checkout B" after doing a
> "git branch -c B", and if that operation is so useful and deserves a
> short-hand way to do so, perhaps extend "git checkout -b B" to copy
> configurations while creating the new branch B.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>
>  * Let's send an updated one as a follow-up to the discussion thread
>    that it is a follow-up to.  The patch in this message is the same
>    as the one I previously sent; the proposed log message has been
>    updated somewhat.
>
>  builtin/branch.c  |  9 +++------
>  t/t3200-branch.sh | 10 +++++-----
>  2 files changed, 8 insertions(+), 11 deletions(-)

This mostly looks good to me.

I've already spent several screenfuls here on-list arguing for not
applying the equivalent of this patch, which I won't repeat here.

But just a brief comment: I think this doing this is good, and it's
something I agree with given that the consensus is going this way. I
thought "do what -m does" was less confusing, but since everyone (you,
Brad, even Sahil) seems to disagree I'm happy to be shown to be wrong &
to have this go in so thoroughly reviewed & thought about.

I do think however that we also need to update the docs, the relevant
origin/master...gitster/sd/branch-copy diff is currently:

    +The `-c` and `-C` options have the exact same semantics as `-m` and
    +`-M`, except instead of the branch being renamed it along with its
    +config and reflog will be copied to a new name.

Suggestions welcome, but I think that should probably be changed to
something like the following as part of this patch:

    The `-c` and `-C` options have the exact same semantics as `-m` and
    `-M`, except instead of the branch being renamed it along with its
    config and reflog will be copied to a new name. Furthermore, unlike
    its `-m` and `-M` cousins the `-c` and `-C` options will never move
    the HEAD, whereas the move option will do so if the source branch is
    the currently checked-out branch.

> diff --git a/builtin/branch.c b/builtin/branch.c
> index 89f64f4123..e2e3692838 100644
> --- a/builtin/branch.c
> +++ b/builtin/branch.c
> @@ -506,12 +506,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
>  				oldref.buf + 11);
>  	}
>
> -	if (replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf)) {
> -		if (copy)
> -			die(_("Branch copied to %s, but HEAD is not updated!"), newname);
> -		else
> -			die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
> -	}
> +	if (!copy &&
> +	    replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
> +		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
>
>  	strbuf_release(&logmsg);
>
> diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
> index 5d03ad16f6..be9b3784c6 100755
> --- a/t/t3200-branch.sh
> +++ b/t/t3200-branch.sh
> @@ -422,7 +422,7 @@ test_expect_success 'git branch --copy is a synonym for -c' '
>  	test_cmp expect actual
>  '
>
> -test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
> +test_expect_success 'git branch -c ee ef should copy to create branch ef' '
>  	git checkout -b ee &&
>  	git reflog exists refs/heads/ee &&
>  	git config branch.ee.dummy Hello &&
> @@ -431,7 +431,7 @@ test_expect_success 'git branch -c ee ef should copy and checkout branch ef' '
>  	git reflog exists refs/heads/ef &&
>  	test $(git config branch.ee.dummy) = Hello &&
>  	test $(git config branch.ef.dummy) = Hello &&
> -	test $(git rev-parse --abbrev-ref HEAD) = ef
> +	test $(git rev-parse --abbrev-ref HEAD) = ee
>  '
>
>  test_expect_success 'git branch -c f/f g/g should work' '
> @@ -494,12 +494,12 @@ test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out'
>  	git checkout -b c1 &&
>  	git branch c2 &&
>  	git branch -C c1 c2 &&
> -	test $(git rev-parse --abbrev-ref HEAD) = c2
> +	test $(git rev-parse --abbrev-ref HEAD) = c1
>  '
>
> -test_expect_success 'git branch -C c1 c2 should add entries to .git/logs/HEAD' '
> +test_expect_success 'git branch -C c1 c2 should never touch HEAD' '
>  	msg="Branch: copied refs/heads/c1 to refs/heads/c2" &&
> -	grep "$msg$" .git/logs/HEAD
> +	! grep "$msg$" .git/logs/HEAD
>  '
>
>  test_expect_success 'git branch -C master should work when master is checked out' '

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/3] branch: fix "copy" to never touch HEAD
  2017-09-26 21:39       ` Ævar Arnfjörð Bjarmason
@ 2017-09-27  2:02         ` Junio C Hamano
  2017-09-29 18:30           ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2017-09-27  2:02 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Sahil Dua, git, Jonathan Nieder, Michael Haggerty,
	Brandon Williams

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> I do think however that we also need to update the docs, the relevant
> origin/master...gitster/sd/branch-copy diff is currently:
>
>     +The `-c` and `-C` options have the exact same semantics as `-m` and
>     +`-M`, except instead of the branch being renamed it along with its
>     +config and reflog will be copied to a new name.
>
> Suggestions welcome, but I think that should probably be changed to
> something like the following as part of this patch:
>
>     The `-c` and `-C` options have the exact same semantics as `-m` and
>     `-M`, except instead of the branch being renamed it along with its
>     config and reflog will be copied to a new name. Furthermore, unlike
>     its `-m` and `-M` cousins the `-c` and `-C` options will never move
>     the HEAD, whereas the move option will do so if the source branch is
>     the currently checked-out branch.

I do not think anybody even _imagines_ copy to move HEAD, and do not
think "unlike -m, it doesn't touch HEAD" a worthwhile thing to say.

It is '-m' whose behaviour may look strange wrt HEAD, so _that_ may
be worth mentioning, though.

I suspect that your reaction probably comes from being too married
to the idea that HEAD has a string that is the same as the refname
of the current branch.  But that is a mere implementation detail.
Users would think that HEAD points at the current branch and does
not even care how that pointing is implemented.

Conceptually, you can consider that each branch has its own
identity, separate from various traits it has, like what its
upstream branch is, what commit it points at, what its reflog says,
and (most notably) what its name is.

Then you can think of "branch -m old new" to be (1) finding the
instance of branch that currently has name 'old' and (2) updating
only one of its trait, namely, its name, without changing anything
else.  Creating a new instance of a branch by copying an existing
one, on the other hand, would then be the matter of (1) finding the
instance of branch with name 'old' and (2) creating another instance
of branch with the same traits as the original, modulo its name is
set to 'new'.

A necessary wrinkle for "branch -m" that falls out of the above
world model is that HEAD needs to be adjusted in order to keep
pointing at the same (renamed) instance of branch that now has an
updated name, if HEAD happened to be pointing at the instance of the
branch whose name trait has been updated.

So, from that point of view, I'd prefer to do something like the
attached patch instead.  I notice that "branch -m" does not mention
configuration variables carried over to the new branch, but I do not
necessarily think we want to exhaustively enumerate what traits are
carried over here, so perhaps it is OK as is.

 Documentation/git-branch.txt | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index fe029ac6fc..d425e3acd4 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -63,11 +63,13 @@ With a `-m` or `-M` option, <oldbranch> will be renamed to <newbranch>.
 If <oldbranch> had a corresponding reflog, it is renamed to match
 <newbranch>, and a reflog entry is created to remember the branch
 renaming. If <newbranch> exists, -M must be used to force the rename
-to happen.
+to happen.  If you rename a branch that is currently checked out,
+`HEAD` is adjusted so that the branch (whose name is now
+<newbranch>) stays to be the current branch.
 
-The `-c` and `-C` options have the exact same semantics as `-m` and
-`-M`, except instead of the branch being renamed it along with its
-config and reflog will be copied to a new name.
+With a `-c` or`-C` option, a new branch <newbranch> is created by
+copying the traits like the reflog contents and `branch.*.*`
+configuration from an existing <oldbranch>.
 
 With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
 specify more than one branch for deletion.  If the branch currently

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/3] branch: fix "copy" to never touch HEAD
  2017-09-27  2:02         ` Junio C Hamano
@ 2017-09-29 18:30           ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 14+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2017-09-29 18:30 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Sahil Dua, git, Jonathan Nieder, Michael Haggerty,
	Brandon Williams


On Wed, Sep 27 2017, Junio C. Hamano jotted:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> I do think however that we also need to update the docs, the relevant
>> origin/master...gitster/sd/branch-copy diff is currently:
>>
>>     +The `-c` and `-C` options have the exact same semantics as `-m` and
>>     +`-M`, except instead of the branch being renamed it along with its
>>     +config and reflog will be copied to a new name.
>>
>> Suggestions welcome, but I think that should probably be changed to
>> something like the following as part of this patch:
>>
>>     The `-c` and `-C` options have the exact same semantics as `-m` and
>>     `-M`, except instead of the branch being renamed it along with its
>>     config and reflog will be copied to a new name. Furthermore, unlike
>>     its `-m` and `-M` cousins the `-c` and `-C` options will never move
>>     the HEAD, whereas the move option will do so if the source branch is
>>     the currently checked-out branch.
>
> I do not think anybody even _imagines_ copy to move HEAD, and do not
> think "unlike -m, it doesn't touch HEAD" a worthwhile thing to say.
>
> It is '-m' whose behaviour may look strange wrt HEAD, so _that_ may
> be worth mentioning, though.
>
> I suspect that your reaction probably comes from being too married
> to the idea that HEAD has a string that is the same as the refname
> of the current branch.  But that is a mere implementation detail.
> Users would think that HEAD points at the current branch and does
> not even care how that pointing is implemented.

To cut to the chase instead of pointlessly replying to this
point-by-point, I think your patch quoted below is good and solves the
minor doc issue I had with your patch.

Yes HEAD is an implementation detail, but it's an exposed implementation
detail.

Thus before your patch it was true to say that "[-c] has the exact same
semantics as [-m] [...] except [ s/move/rename/ ]" since that was the
only behavior change, but with your patch adding another "if (!copy &&
...)" we'd now have two things different in the code, but only one thing
enumerated as being different in the docs.

Just rephrasing it as you did is a better way out of that than my
proposed patch. Thanks.

> Conceptually, you can consider that each branch has its own
> identity, separate from various traits it has, like what its
> upstream branch is, what commit it points at, what its reflog says,
> and (most notably) what its name is.
>
> Then you can think of "branch -m old new" to be (1) finding the
> instance of branch that currently has name 'old' and (2) updating
> only one of its trait, namely, its name, without changing anything
> else.  Creating a new instance of a branch by copying an existing
> one, on the other hand, would then be the matter of (1) finding the
> instance of branch with name 'old' and (2) creating another instance
> of branch with the same traits as the original, modulo its name is
> set to 'new'.
>
> A necessary wrinkle for "branch -m" that falls out of the above
> world model is that HEAD needs to be adjusted in order to keep
> pointing at the same (renamed) instance of branch that now has an
> updated name, if HEAD happened to be pointing at the instance of the
> branch whose name trait has been updated.
>
> So, from that point of view, I'd prefer to do something like the
> attached patch instead.  I notice that "branch -m" does not mention
> configuration variables carried over to the new branch, but I do not
> necessarily think we want to exhaustively enumerate what traits are
> carried over here, so perhaps it is OK as is.
>
>  Documentation/git-branch.txt | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
> index fe029ac6fc..d425e3acd4 100644
> --- a/Documentation/git-branch.txt
> +++ b/Documentation/git-branch.txt
> @@ -63,11 +63,13 @@ With a `-m` or `-M` option, <oldbranch> will be renamed to <newbranch>.
>  If <oldbranch> had a corresponding reflog, it is renamed to match
>  <newbranch>, and a reflog entry is created to remember the branch
>  renaming. If <newbranch> exists, -M must be used to force the rename
> -to happen.
> +to happen.  If you rename a branch that is currently checked out,
> +`HEAD` is adjusted so that the branch (whose name is now
> +<newbranch>) stays to be the current branch.
>
> -The `-c` and `-C` options have the exact same semantics as `-m` and
> -`-M`, except instead of the branch being renamed it along with its
> -config and reflog will be copied to a new name.
> +With a `-c` or`-C` option, a new branch <newbranch> is created by
> +copying the traits like the reflog contents and `branch.*.*`
> +configuration from an existing <oldbranch>.
>
>  With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
>  specify more than one branch for deletion.  If the branch currently

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2017-09-29 18:30 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-05 22:35 What's cooking in git.git (Jul 2017, #01; Wed, 5) Junio C Hamano
2017-07-05 23:06 ` Stefan Beller
2017-07-07  2:13   ` Junio C Hamano
2017-07-10 17:27     ` Stefan Beller
2017-07-05 23:14 ` [PATCH v2 0/3] branch: add a --copy to go with --move Ævar Arnfjörð Bjarmason
2017-07-06  0:37   ` Junio C Hamano
2017-09-22  4:57     ` [PATCH 4/3] branch: fix "copy" to never touch HEAD Junio C Hamano
2017-09-22 16:33       ` Brandon Williams
2017-09-26 21:39       ` Ævar Arnfjörð Bjarmason
2017-09-27  2:02         ` Junio C Hamano
2017-09-29 18:30           ` Ævar Arnfjörð Bjarmason
2017-07-05 23:14 ` [PATCH v2 1/3] config: create a function to format section headers Ævar Arnfjörð Bjarmason
2017-07-05 23:14 ` [PATCH v2 2/3] branch: add test for -m renaming multiple config sections Ævar Arnfjörð Bjarmason
2017-07-05 23:14 ` [PATCH v2 3/3] branch: add a --copy (-c) option to go with --move (-m) Ævar Arnfjörð Bjarmason

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).