mirror of
https://github.com/git/git.git
synced 2026-01-11 13:23:12 +09:00
When rewriting history via git-rebase(1) there are a few very common use
cases:
- The ordering of two commits should be reversed.
- A commit should be split up into two commits.
- A commit should be dropped from the history completely.
- Multiple commits should be squashed into one.
- Editing an existing commit that is not the tip of the current
branch.
While these operations are all doable, it often feels needlessly kludgey
to do so by doing an interactive rebase, using the editor to say what
one wants, and then perform the actions. Also, some operations like
splitting up a commit into two are way more involved than that and
require a whole series of commands.
Rebases also do not update dependent branches. The use of stacked
branches has grown quite common with competing version control systems
like Jujutsu though, so it clearly is a need that users have. While
rebases _can_ serve this use case if one always works on the latest
stacked branch, it is somewhat awkward and very easy to get wrong.
Add a new "history" command to plug these gaps. This command will have
several different subcommands to imperatively rewrite history for common
use cases like the above.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
544 lines
14 KiB
Meson
544 lines
14 KiB
Meson
manpages = {
|
|
# Category 1.
|
|
'git-add.adoc' : 1,
|
|
'git-am.adoc' : 1,
|
|
'git-annotate.adoc' : 1,
|
|
'git-apply.adoc' : 1,
|
|
'git-archimport.adoc' : 1,
|
|
'git-archive.adoc' : 1,
|
|
'git-backfill.adoc' : 1,
|
|
'git-bisect.adoc' : 1,
|
|
'git-blame.adoc' : 1,
|
|
'git-branch.adoc' : 1,
|
|
'git-bugreport.adoc' : 1,
|
|
'git-bundle.adoc' : 1,
|
|
'git-cat-file.adoc' : 1,
|
|
'git-check-attr.adoc' : 1,
|
|
'git-check-ignore.adoc' : 1,
|
|
'git-check-mailmap.adoc' : 1,
|
|
'git-checkout-index.adoc' : 1,
|
|
'git-checkout.adoc' : 1,
|
|
'git-check-ref-format.adoc' : 1,
|
|
'git-cherry-pick.adoc' : 1,
|
|
'git-cherry.adoc' : 1,
|
|
'git-citool.adoc' : 1,
|
|
'git-clean.adoc' : 1,
|
|
'git-clone.adoc' : 1,
|
|
'git-column.adoc' : 1,
|
|
'git-commit-graph.adoc' : 1,
|
|
'git-commit-tree.adoc' : 1,
|
|
'git-commit.adoc' : 1,
|
|
'git-config.adoc' : 1,
|
|
'git-count-objects.adoc' : 1,
|
|
'git-credential-cache--daemon.adoc' : 1,
|
|
'git-credential-cache.adoc' : 1,
|
|
'git-credential-store.adoc' : 1,
|
|
'git-credential.adoc' : 1,
|
|
'git-cvsexportcommit.adoc' : 1,
|
|
'git-cvsimport.adoc' : 1,
|
|
'git-cvsserver.adoc' : 1,
|
|
'git-daemon.adoc' : 1,
|
|
'git-describe.adoc' : 1,
|
|
'git-diagnose.adoc' : 1,
|
|
'git-diff-files.adoc' : 1,
|
|
'git-diff-index.adoc' : 1,
|
|
'git-diff-pairs.adoc' : 1,
|
|
'git-difftool.adoc' : 1,
|
|
'git-diff-tree.adoc' : 1,
|
|
'git-diff.adoc' : 1,
|
|
'git-fast-export.adoc' : 1,
|
|
'git-fast-import.adoc' : 1,
|
|
'git-fetch-pack.adoc' : 1,
|
|
'git-fetch.adoc' : 1,
|
|
'git-filter-branch.adoc' : 1,
|
|
'git-fmt-merge-msg.adoc' : 1,
|
|
'git-for-each-ref.adoc' : 1,
|
|
'git-for-each-repo.adoc' : 1,
|
|
'git-format-patch.adoc' : 1,
|
|
'git-fsck-objects.adoc' : 1,
|
|
'git-fsck.adoc' : 1,
|
|
'git-fsmonitor--daemon.adoc' : 1,
|
|
'git-gc.adoc' : 1,
|
|
'git-get-tar-commit-id.adoc' : 1,
|
|
'git-grep.adoc' : 1,
|
|
'git-gui.adoc' : 1,
|
|
'git-hash-object.adoc' : 1,
|
|
'git-help.adoc' : 1,
|
|
'git-history.adoc' : 1,
|
|
'git-hook.adoc' : 1,
|
|
'git-http-backend.adoc' : 1,
|
|
'git-http-fetch.adoc' : 1,
|
|
'git-http-push.adoc' : 1,
|
|
'git-imap-send.adoc' : 1,
|
|
'git-index-pack.adoc' : 1,
|
|
'git-init-db.adoc' : 1,
|
|
'git-init.adoc' : 1,
|
|
'git-instaweb.adoc' : 1,
|
|
'git-interpret-trailers.adoc' : 1,
|
|
'git-last-modified.adoc' : 1,
|
|
'git-log.adoc' : 1,
|
|
'git-ls-files.adoc' : 1,
|
|
'git-ls-remote.adoc' : 1,
|
|
'git-ls-tree.adoc' : 1,
|
|
'git-mailinfo.adoc' : 1,
|
|
'git-mailsplit.adoc' : 1,
|
|
'git-maintenance.adoc' : 1,
|
|
'git-merge-base.adoc' : 1,
|
|
'git-merge-file.adoc' : 1,
|
|
'git-merge-index.adoc' : 1,
|
|
'git-merge-one-file.adoc' : 1,
|
|
'git-mergetool--lib.adoc' : 1,
|
|
'git-mergetool.adoc' : 1,
|
|
'git-merge-tree.adoc' : 1,
|
|
'git-merge.adoc' : 1,
|
|
'git-mktag.adoc' : 1,
|
|
'git-mktree.adoc' : 1,
|
|
'git-multi-pack-index.adoc' : 1,
|
|
'git-mv.adoc' : 1,
|
|
'git-name-rev.adoc' : 1,
|
|
'git-notes.adoc' : 1,
|
|
'git-p4.adoc' : 1,
|
|
'git-pack-objects.adoc' : 1,
|
|
'git-pack-refs.adoc' : 1,
|
|
'git-patch-id.adoc' : 1,
|
|
'git-prune-packed.adoc' : 1,
|
|
'git-prune.adoc' : 1,
|
|
'git-pull.adoc' : 1,
|
|
'git-push.adoc' : 1,
|
|
'git-quiltimport.adoc' : 1,
|
|
'git-range-diff.adoc' : 1,
|
|
'git-read-tree.adoc' : 1,
|
|
'git-rebase.adoc' : 1,
|
|
'git-receive-pack.adoc' : 1,
|
|
'git-reflog.adoc' : 1,
|
|
'git-refs.adoc' : 1,
|
|
'git-remote-ext.adoc' : 1,
|
|
'git-remote-fd.adoc' : 1,
|
|
'git-remote.adoc' : 1,
|
|
'git-repack.adoc' : 1,
|
|
'git-replace.adoc' : 1,
|
|
'git-replay.adoc' : 1,
|
|
'git-repo.adoc' : 1,
|
|
'git-request-pull.adoc' : 1,
|
|
'git-rerere.adoc' : 1,
|
|
'git-reset.adoc' : 1,
|
|
'git-restore.adoc' : 1,
|
|
'git-revert.adoc' : 1,
|
|
'git-rev-list.adoc' : 1,
|
|
'git-rev-parse.adoc' : 1,
|
|
'git-rm.adoc' : 1,
|
|
'git-send-email.adoc' : 1,
|
|
'git-send-pack.adoc' : 1,
|
|
'git-shell.adoc' : 1,
|
|
'git-sh-i18n--envsubst.adoc' : 1,
|
|
'git-sh-i18n.adoc' : 1,
|
|
'git-shortlog.adoc' : 1,
|
|
'git-show-branch.adoc' : 1,
|
|
'git-show-index.adoc' : 1,
|
|
'git-show-ref.adoc' : 1,
|
|
'git-show.adoc' : 1,
|
|
'git-sh-setup.adoc' : 1,
|
|
'git-sparse-checkout.adoc' : 1,
|
|
'git-stage.adoc' : 1,
|
|
'git-stash.adoc' : 1,
|
|
'git-status.adoc' : 1,
|
|
'git-stripspace.adoc' : 1,
|
|
'git-submodule.adoc' : 1,
|
|
'git-svn.adoc' : 1,
|
|
'git-switch.adoc' : 1,
|
|
'git-symbolic-ref.adoc' : 1,
|
|
'git-tag.adoc' : 1,
|
|
'git-unpack-file.adoc' : 1,
|
|
'git-unpack-objects.adoc' : 1,
|
|
'git-update-index.adoc' : 1,
|
|
'git-update-ref.adoc' : 1,
|
|
'git-update-server-info.adoc' : 1,
|
|
'git-upload-archive.adoc' : 1,
|
|
'git-upload-pack.adoc' : 1,
|
|
'git-var.adoc' : 1,
|
|
'git-verify-commit.adoc' : 1,
|
|
'git-verify-pack.adoc' : 1,
|
|
'git-verify-tag.adoc' : 1,
|
|
'git-version.adoc' : 1,
|
|
'git-web--browse.adoc' : 1,
|
|
'git-worktree.adoc' : 1,
|
|
'git-write-tree.adoc' : 1,
|
|
'git.adoc' : 1,
|
|
'gitk.adoc' : 1,
|
|
'gitweb.adoc' : 1,
|
|
'scalar.adoc' : 1,
|
|
|
|
# Category 5.
|
|
'gitattributes.adoc' : 5,
|
|
'gitformat-bundle.adoc' : 5,
|
|
'gitformat-chunk.adoc' : 5,
|
|
'gitformat-commit-graph.adoc' : 5,
|
|
'gitformat-index.adoc' : 5,
|
|
'gitformat-loose.adoc' : 5,
|
|
'gitformat-pack.adoc' : 5,
|
|
'gitformat-signature.adoc' : 5,
|
|
'githooks.adoc' : 5,
|
|
'gitignore.adoc' : 5,
|
|
'gitmailmap.adoc' : 5,
|
|
'gitmodules.adoc' : 5,
|
|
'gitprotocol-capabilities.adoc' : 5,
|
|
'gitprotocol-common.adoc' : 5,
|
|
'gitprotocol-http.adoc' : 5,
|
|
'gitprotocol-pack.adoc' : 5,
|
|
'gitprotocol-v2.adoc' : 5,
|
|
'gitrepository-layout.adoc' : 5,
|
|
'gitweb.conf.adoc' : 5,
|
|
|
|
# Category 7.
|
|
'gitcli.adoc' : 7,
|
|
'gitcore-tutorial.adoc' : 7,
|
|
'gitcredentials.adoc' : 7,
|
|
'gitcvs-migration.adoc' : 7,
|
|
'gitdatamodel.adoc' : 7,
|
|
'gitdiffcore.adoc' : 7,
|
|
'giteveryday.adoc' : 7,
|
|
'gitfaq.adoc' : 7,
|
|
'gitglossary.adoc' : 7,
|
|
'gitpacking.adoc' : 7,
|
|
'gitnamespaces.adoc' : 7,
|
|
'gitremote-helpers.adoc' : 7,
|
|
'gitrevisions.adoc' : 7,
|
|
'gitsubmodules.adoc' : 7,
|
|
'gittutorial-2.adoc' : 7,
|
|
'gittutorial.adoc' : 7,
|
|
'gitworkflows.adoc' : 7,
|
|
}
|
|
|
|
manpages_breaking_changes = {
|
|
'git-pack-redundant.adoc' : 1,
|
|
'git-whatchanged.adoc' : 1,
|
|
}
|
|
|
|
if not get_option('breaking_changes')
|
|
manpages += manpages_breaking_changes
|
|
endif
|
|
|
|
docs_backend = get_option('docs_backend')
|
|
if docs_backend == 'auto'
|
|
if find_program('asciidoc', dirs: program_path, native: true, required: false).found()
|
|
docs_backend = 'asciidoc'
|
|
elif find_program('asciidoctor', dirs: program_path, native: true, required: false).found()
|
|
docs_backend = 'asciidoctor'
|
|
else
|
|
error('Neither asciidoc nor asciidoctor were found.')
|
|
endif
|
|
endif
|
|
|
|
if docs_backend == 'asciidoc'
|
|
asciidoc = find_program('asciidoc', dirs: program_path, native: true)
|
|
asciidoc_html = 'xhtml11'
|
|
asciidoc_docbook = 'docbook'
|
|
xmlto_extra = [ ]
|
|
|
|
asciidoc_conf = custom_target(
|
|
command: [
|
|
shell,
|
|
meson.project_source_root() / 'GIT-VERSION-GEN',
|
|
meson.project_source_root(),
|
|
'@INPUT@',
|
|
'@OUTPUT@',
|
|
],
|
|
input: 'asciidoc.conf.in',
|
|
output: 'asciidoc.conf',
|
|
depends: [git_version_file],
|
|
env: version_gen_environment,
|
|
)
|
|
|
|
asciidoc_common_options = [
|
|
asciidoc,
|
|
'--conf-file=' + asciidoc_conf.full_path(),
|
|
'--attribute=build_dir=' + meson.current_build_dir(),
|
|
]
|
|
|
|
pager_opt = get_option('default_pager')
|
|
if pager_opt != '' and pager_opt != 'less'
|
|
asciidoc_common_options += '-agit-default-pager=' + pager_opt
|
|
endif
|
|
|
|
editor_opt = get_option('default_editor')
|
|
if editor_opt != '' and editor_opt != 'vi'
|
|
asciidoc_common_options += '-agit-default-editor=' + editor_opt
|
|
endif
|
|
|
|
documentation_deps = [
|
|
asciidoc_conf,
|
|
]
|
|
elif docs_backend == 'asciidoctor'
|
|
asciidoctor = find_program('asciidoctor', dirs: program_path, native: true)
|
|
asciidoc_html = 'xhtml5'
|
|
asciidoc_docbook = 'docbook5'
|
|
xmlto_extra = [
|
|
'--skip-validation',
|
|
'-x', meson.current_source_dir() / 'manpage.xsl',
|
|
]
|
|
|
|
asciidoctor_extensions = custom_target(
|
|
command: [
|
|
shell,
|
|
meson.project_source_root() / 'GIT-VERSION-GEN',
|
|
meson.project_source_root(),
|
|
'@INPUT@',
|
|
'@OUTPUT@',
|
|
],
|
|
input: 'asciidoctor-extensions.rb.in',
|
|
output: 'asciidoctor-extensions.rb',
|
|
depends: [git_version_file],
|
|
env: version_gen_environment,
|
|
)
|
|
|
|
asciidoc_common_options = [
|
|
asciidoctor,
|
|
'--attribute', 'compat-mode',
|
|
'--attribute', 'tabsize=8',
|
|
'--attribute', 'litdd=--',
|
|
'--attribute', 'docinfo=shared',
|
|
'--attribute', 'build_dir=' + meson.current_build_dir(),
|
|
'--load-path', meson.current_build_dir(),
|
|
'--require', 'asciidoctor-extensions',
|
|
]
|
|
|
|
pager_opt = get_option('default_pager')
|
|
if pager_opt != '' and pager_opt != 'less'
|
|
asciidoc_common_options += '-agit-default-pager=' + pager_opt
|
|
endif
|
|
|
|
editor_opt = get_option('default_editor')
|
|
if editor_opt != '' and editor_opt != 'vi'
|
|
asciidoc_common_options += '-agit-default-editor=' + editor_opt
|
|
endif
|
|
|
|
documentation_deps = [
|
|
asciidoctor_extensions,
|
|
]
|
|
endif
|
|
|
|
if get_option('breaking_changes')
|
|
asciidoc_common_options += ['--attribute', 'with-breaking-changes']
|
|
endif
|
|
|
|
xmlto = find_program('xmlto', dirs: program_path, native: true)
|
|
|
|
cmd_lists = [
|
|
'cmds-ancillaryinterrogators.adoc',
|
|
'cmds-ancillarymanipulators.adoc',
|
|
'cmds-mainporcelain.adoc',
|
|
'cmds-plumbinginterrogators.adoc',
|
|
'cmds-plumbingmanipulators.adoc',
|
|
'cmds-synchingrepositories.adoc',
|
|
'cmds-synchelpers.adoc',
|
|
'cmds-guide.adoc',
|
|
'cmds-developerinterfaces.adoc',
|
|
'cmds-userinterfaces.adoc',
|
|
'cmds-purehelpers.adoc',
|
|
'cmds-foreignscminterface.adoc',
|
|
]
|
|
|
|
documentation_deps += custom_target(
|
|
command: [
|
|
shell,
|
|
'@INPUT@',
|
|
meson.project_source_root(),
|
|
meson.current_build_dir(),
|
|
] + cmd_lists,
|
|
input: 'cmd-list.sh',
|
|
output: cmd_lists
|
|
)
|
|
|
|
foreach mode : [ 'diff', 'merge' ]
|
|
documentation_deps += custom_target(
|
|
command: [
|
|
shell,
|
|
'@INPUT@',
|
|
'..',
|
|
mode,
|
|
'@OUTPUT@'
|
|
],
|
|
env: [
|
|
'MERGE_TOOLS_DIR=' + meson.project_source_root() / 'mergetools',
|
|
],
|
|
input: 'generate-mergetool-list.sh',
|
|
output: 'mergetools-' + mode + '.adoc',
|
|
)
|
|
endforeach
|
|
|
|
foreach manpage, category : manpages
|
|
if get_option('docs').contains('man')
|
|
manpage_xml_target = custom_target(
|
|
command: asciidoc_common_options + [
|
|
'--backend=' + asciidoc_docbook,
|
|
'--doctype=manpage',
|
|
'--out-file=@OUTPUT@',
|
|
'@INPUT@',
|
|
],
|
|
depends: documentation_deps,
|
|
input: manpage,
|
|
output: fs.stem(manpage) + '.xml',
|
|
)
|
|
|
|
doc_targets += custom_target(
|
|
command: [
|
|
xmlto,
|
|
'-m', '@INPUT0@',
|
|
'-m', '@INPUT1@',
|
|
'--stringparam',
|
|
'man.base.url.for.relative.links=' + get_option('prefix') / get_option('mandir'),
|
|
'man',
|
|
manpage_xml_target,
|
|
'-o',
|
|
meson.current_build_dir(),
|
|
] + xmlto_extra,
|
|
input: [
|
|
'manpage-normal.xsl',
|
|
'manpage-bold-literal.xsl',
|
|
],
|
|
output: fs.stem(manpage) + '.' + category.to_string(),
|
|
install: true,
|
|
install_dir: get_option('mandir') / 'man' + category.to_string(),
|
|
)
|
|
endif
|
|
|
|
if get_option('docs').contains('html')
|
|
doc_targets += custom_target(
|
|
command: asciidoc_common_options + [
|
|
'--backend=' + asciidoc_html,
|
|
'--doctype=manpage',
|
|
'--out-file=@OUTPUT@',
|
|
'@INPUT@',
|
|
],
|
|
depends: documentation_deps,
|
|
input: manpage,
|
|
output: fs.stem(manpage) + '.html',
|
|
install: true,
|
|
install_dir: htmldir,
|
|
)
|
|
endif
|
|
endforeach
|
|
|
|
if get_option('docs').contains('html')
|
|
configure_file(
|
|
input: 'docinfo-html.in',
|
|
output: 'docinfo.html',
|
|
copy: true,
|
|
install: true,
|
|
install_dir: htmldir,
|
|
)
|
|
|
|
configure_file(
|
|
input: 'docbook-xsl.css',
|
|
output: 'docbook-xsl.css',
|
|
copy: true,
|
|
install: true,
|
|
install_dir: htmldir,
|
|
)
|
|
|
|
install_symlink('index.html',
|
|
install_dir: htmldir,
|
|
pointing_to: 'git.html',
|
|
)
|
|
|
|
xsltproc = find_program('xsltproc', dirs: program_path, native: true)
|
|
|
|
user_manual_xml = custom_target(
|
|
command: asciidoc_common_options + [
|
|
'--backend=' + asciidoc_docbook,
|
|
'--doctype=book',
|
|
'--out-file=@OUTPUT@',
|
|
'@INPUT@',
|
|
],
|
|
input: 'user-manual.adoc',
|
|
output: 'user-manual.xml',
|
|
depends: documentation_deps,
|
|
)
|
|
|
|
doc_targets += custom_target(
|
|
command: [
|
|
xsltproc,
|
|
'--xinclude',
|
|
'--stringparam', 'html.stylesheet', 'docbook-xsl.css',
|
|
'--param', 'generate.consistent.ids', '1',
|
|
'--output', '@OUTPUT@',
|
|
'@INPUT@',
|
|
user_manual_xml,
|
|
],
|
|
input: 'docbook.xsl',
|
|
output: 'user-manual.html',
|
|
install: true,
|
|
install_dir: htmldir,
|
|
)
|
|
|
|
articles = [
|
|
'BreakingChanges.adoc',
|
|
'DecisionMaking.adoc',
|
|
'MyFirstContribution.adoc',
|
|
'MyFirstObjectWalk.adoc',
|
|
'ReviewingGuidelines.adoc',
|
|
'SubmittingPatches',
|
|
'ToolsForGit.adoc',
|
|
'git-bisect-lk2009.adoc',
|
|
'git-tools.adoc',
|
|
]
|
|
|
|
foreach article : articles
|
|
doc_targets += custom_target(
|
|
command: asciidoc_common_options + [
|
|
'--backend=' + asciidoc_html,
|
|
'--out-file=@OUTPUT@',
|
|
'@INPUT@',
|
|
],
|
|
input: article,
|
|
output: fs.stem(article) + '.html',
|
|
depends: documentation_deps,
|
|
install: true,
|
|
install_dir: htmldir,
|
|
)
|
|
endforeach
|
|
|
|
asciidoc_html_options = asciidoc_common_options + [
|
|
'--backend=' + asciidoc_html,
|
|
'--out-file=@OUTPUT@',
|
|
'--attribute', 'git-relative-html-prefix=../',
|
|
'@INPUT@',
|
|
]
|
|
|
|
subdir('howto')
|
|
subdir('technical')
|
|
endif
|
|
|
|
# Sanity check that we are not missing any tests present in 't/'. This check
|
|
# only runs once at configure time and is thus best-effort, only. Furthermore,
|
|
# it only verifies man pages for the sake of simplicity.
|
|
configured_manpages = manpages.keys()
|
|
configured_manpages += manpages_breaking_changes.keys()
|
|
configured_manpages += [ 'git-bisect-lk2009.adoc', 'git-tools.adoc' ]
|
|
actual_manpages = run_command(shell, '-c', 'ls git*.adoc scalar.adoc',
|
|
check: true,
|
|
env: script_environment,
|
|
).stdout().strip().split('\n')
|
|
|
|
if configured_manpages != actual_manpages
|
|
missing_manpage = [ ]
|
|
foreach actual_manpage : actual_manpages
|
|
if actual_manpage not in configured_manpages
|
|
missing_manpage += actual_manpage
|
|
endif
|
|
endforeach
|
|
if missing_manpage.length() > 0
|
|
error('Man page found, but not configured:\n\n - ' + '\n - '.join(missing_manpage))
|
|
endif
|
|
|
|
superfluous_manpage = [ ]
|
|
foreach configured_manpage : configured_manpages
|
|
if configured_manpage not in actual_manpages
|
|
superfluous_manpage += configured_manpage
|
|
endif
|
|
endforeach
|
|
if superfluous_manpage.length() > 0
|
|
error('Man page configured, but not found:\n\n - ' + '\n - '.join(superfluous_manpage))
|
|
endif
|
|
endif
|