git_well.git_squash_streaks module

This git-squash-streaks command

Requirements:

pip install ubelt pip install GitPython pip install scriptconfig

class git_well.git_squash_streaks.SquashStreakCLI(*args, **kwargs)[source]

Bases: DataConfig

Squashes consecutive commits that meet a specified criteiron.

Valid options: []

Parameters:
  • *args – positional arguments for this data config

  • **kwargs – keyword arguments for this data config

default = {'authors': <Value(None)>, 'auto_rollback': <Value(False)>, 'custom_streak': <Value(None)>, 'dry': <Value(True)>, 'force': <Value(None)>, 'inplace': <Value(False)>, 'oldest_commit': <Value(None)>, 'pattern': <Value(None)>, 'preserve_tags': <Value(True)>, 'tags': <Value(False)>, 'timedelta': <Value('sameday')>, 'verbose': <Value(True)>}
main(**kwargs)

git-squash-streaks

Usage:

See argparse

normalize()
git_well.git_squash_streaks.print_exc(exc_info=None)[source]

Example

>>> try:
>>>     raise Exception('foobar')
>>> except Exception as ex:
>>>     import sys
>>>     exc_info = sys.exc_info()
>>>     print_exc(exc_info)
class git_well.git_squash_streaks.Streak(child, _streak=None)[source]

Bases: NiceRepr

append(commit)[source]
property before_start
property after_stop
property start
property stop
git_well.git_squash_streaks.find_pseudo_chain(head, oldest_commit=None, preserve_tags=True)[source]

Finds start and end points that can be safely squashed between

CommandLine

xdoctest -m git_well.git_squash_streaks find_pseudo_chain

Example

>>> # xdoctest: +REQUIRES(LINUX)
>>> from git_well.git_squash_streaks import *  # NOQA
>>> import git
>>> from git_well import demo
>>> repo_dpath = demo.make_dummy_git_repo()
>>> repo = git.Repo(repo_dpath)
>>> head = repo.commit('HEAD')
>>> pseudo_chain = find_pseudo_chain(head)
>>> print('pseudo_chain = {}'.format(ub.urepr(pseudo_chain, nl=1)))
git_well.git_squash_streaks.git_nx_graph(head, oldest_commit=None, preserve_tags=False)[source]

Example

>>> # xdoctest: +REQUIRES(LINUX)
>>> from git_well.git_squash_streaks import *  # NOQA
>>> from git_well import demo
>>> import git
>>> repo_dpath = demo.make_dummy_git_repo()
>>> repo = git.Repo(repo_dpath)
>>> head = repo.commit('HEAD')
>>> oldest_commit = 'master'
>>> oldest_commit = None
>>> graph = git_nx_graph(head, oldest_commit)
git_well.git_squash_streaks.find_chain(head, authors=None, preserve_tags=True, oldest_commit=None)[source]

Find a chain of commits starting at the HEAD. If authors is specified the commits must be from one of these authors.

The term chain is used in the graph-theory sense. It is a list of commits where all non-endpoint commits have exactly one parent and one child.

Todo

  • [ ] allow a chain to include branches if all messages on all branches

    conform to the chain pattern (e.g. wip)

def search(node, current_path):
if current_path:

pass

child_paths = [] for parent in node.parents:

path = search(parent, current_path) child_paths.append(path)

if len(child_paths) == 0:

pass

if len(child_paths) == 1:

# normal one parent case pass

else:

pass # Branching case # ACCEPT THE BRANCHING PATHS IF: # * PARENT OF ALL PATHS HAVE A COMMON ENDPOINT # * HANDLE CASE WHERE PATHS OVERLAPS

Parameters:
  • head (Commit) – starting point

  • authors (set) – valid authors

  • preserve_tags (bool) – if True the chain is not allowed to extend past any tags. If a set, then we will not procede past any tag with a name in the set. Defaults to True

Example

>>> # xdoctest: +REQUIRES(LINUX)
>>> # assuming you are in a git repo
>>> import git
>>> from git_well.git_squash_streaks import *  # NOQA
>>> from git_well.git_squash_streaks import _squash_between
>>> from git_well import demo
>>> repo_dpath = demo.make_dummy_git_repo()
>>> repo = git.Repo(repo_dpath)
>>> chain = find_chain(repo.head.commit)
git_well.git_squash_streaks.find_streaks(chain, authors=None, timedelta='sameday', pattern=None)[source]

Given a chain, finds subchains (called streaks) that have the same author and are within a timedelta threshold of each other.

Parameters:
  • chain (List[Commit]) – from find_chain

  • authors (set) – valid authors

  • timedelta (float | str) – minimum time between commits in seconds or a categorical value such as ‘sameday’ or ‘alltime’

  • pattern (str) – instead of squashing messages with the same name, squash only if they match this pattern Defaults to None, None means the consecutive messages should match.

git_well.git_squash_streaks.checkout_temporary_branch(repo, suffix='-temp-script-branch')[source]

Changes to a temporary branch so we don’t messup anything on the main one.

If the temporary branch exists, it is deleted, so make sure you choose your suffix so that it never conflicts with any real branches.

git_well.git_squash_streaks.commits_between(repo, start, stop)[source]
Parameters:
  • start (Commit) – toplogically first (i.e. chronologically older) commit

  • stop (Commit) – toplogically last (i.e. chronologically newer) commit

Returns:

between commits

Return type:

List[Commit]

References

https://stackoverflow.com/questions/18679870/commits-between-2-hashes https://stackoverflow.com/questions/462974/diff-double-and-triple-dot

Warning

this gets messy any node on the path between <start> and <stop> has more than one parent that is not on a path between <start> and <stop>

Notes

As a prefix: the carrot (^A) removes commits reachable from A. As a suffix: the carrot (A^) references the 1st parent of A Furthermore:

(A^n) references the n-th parent of A (A~n) references the n-th ancestor of A The tilde and carrot can be chained. A^^ = A~2 = the grandparent of A

Reachable means everything in the past.

PAST………………………….PRESENT <p1> – <start> – <A> – <B> – <stop>

/

<p2> __/

Example

>>> # xdoctest: +REQUIRES(LINUX)
>>> from git_well.git_squash_streaks import *  # NOQA
>>> from git_well import demo
>>> import git
>>> repo_dpath = demo.make_dummy_git_repo()
>>> repo = git.Repo(repo_dpath)
>>> stop = repo.head.commit
>>> start = stop.parents[0].parents[0].parents[0].parents[0]
>>> commits = commits_between(repo, start, stop)
>>> assert commits[0] == stop
>>> assert commits[-1] == start
>>> assert len(commits) == 5
exception git_well.git_squash_streaks.RollbackError[source]

Bases: Exception

git_well.git_squash_streaks._squash_between(repo, start, stop, dry=False, verbose=True)[source]

inplace squash between, use external function that sets up temp branches to use this directly from the commandline.

git_well.git_squash_streaks.do_tags(verbose=True, inplace=False, dry=True, auto_rollback=False)[source]
git_well.git_squash_streaks.squash_streaks(authors, timedelta='sameday', pattern=None, inplace=False, auto_rollback=True, dry=False, verbose=True, custom_streak=None, preserve_tags=True, oldest_commit=None)[source]

Squashes consecutive commits that meet a specified criteiron.

Parameters:
  • authors (set) – “level-set” of authors who’s commits can be squashed together.

  • timedelta (str or int) – strategy mode or max number of seconds to determine how far appart two commits can be before they are squashed. (Default: ‘sameday’). Valid values: [‘sameday’, ‘alltime’, ‘none’, <n_seconds:float>]

  • pattern (str) – instead of squashing messages with the same name, squash only if they match this pattern (Default: None). Default of None means that squash two commits if they have the same message.

  • inplace (bool) – if True changes will be applied directly to the current branch otherwise a temporary branch will be created. Then you must manually reset the current branch to this branch and delete the temp branch. (Default: False)

  • auto_rollback (bool) – if True the repo will be reset to a clean state if any errors occur. (Default: True)

  • dry (bool) – if True this only executes a dry run, that prints the chains that would be squashed (Default: False)

  • verbose (bool, default=True) – verbosity flag

  • custom_streak (tuple) – hack, specify two commits to explicitly squash only this streak is used. We do not automatically check for others.

  • preserve_tags (bool, default=True) – if True the chain is not allowed to extend past any tags. If a set, then we will not procede past any tag with a name in the set.

  • oldest_commit (str | None) – if specified we will only squash commits toplogically after this commit in the graph.

git_well.git_squash_streaks.git_squash_streaks(cmdline=1, **kwargs)[source]

git-squash-streaks

Usage:

See argparse

git_well.git_squash_streaks.main(cmdline=1, **kwargs)

git-squash-streaks

Usage:

See argparse