diff options
author | Adam Spiers <github@adamspiers.org> | 2019-01-07 19:30:10 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-07 19:30:10 +0000 |
commit | b4e3cd5b3588d29d2bb98ee619f443b24b32395f (patch) | |
tree | 6606eb1a20938d3f7ec34fe1dbda7ccd561a6d3e | |
parent | 66a3a71c4b19350c73e60aaf273e22bf1b86761c (diff) | |
parent | 8e2ec022348d67dd9c354898afb85dd74425bc0a (diff) | |
download | git-deps-b4e3cd5b3588d29d2bb98ee619f443b24b32395f.tar.gz |
Merge pull request #80 from aspiers/README
improve docs
-rw-r--r-- | HISTORY.md | 35 | ||||
-rw-r--r-- | README.md | 327 | ||||
-rw-r--r-- | USAGE.md | 56 | ||||
-rw-r--r-- | USE-CASES.md | 154 |
4 files changed, 361 insertions, 211 deletions
diff --git a/HISTORY.md b/HISTORY.md new file mode 100644 index 0000000..8b010fe --- /dev/null +++ b/HISTORY.md @@ -0,0 +1,35 @@ +History of `git-deps` +======================= + +This tool was born from experiences at +[SUSEcon](http://www.susecon.com/) 2013, when I attempted to help a +colleague backport a bugfix in [OpenStack](http://www.openstack.org/) +[Nova](http://docs.openstack.org/developer/nova/) from the `master` +branch to a stable release branch. At first sight it looked like it +would only require a trivial `git cherry-pick`, but that immediately +revealed conflicts due to related code having changed in `master` +since the release was made. I manually found the underlying commit +which the bugfix required by using `git blame`, and tried another +`cherry-pick`. The same thing happened again. Very soon I found +myself in a quagmire of dependencies between commits, with no idea +whether the end was in sight. + +In coffee breaks during the ensuing openSUSE conference at the same +venue, I feverishly hacked together a prototype and it seemed to work. +Then normal life intervened, and no progress was made for another +year. + +Thanks to SUSE's generous [Hack Week](https://hackweek.suse.com/) +policy, I had the luxury of being able to spending some of early +January 2015 working to bring this tool to the next level. I +submitted a +[Hack Week project page](https://hackweek.suse.com/11/projects/366) +and +[announced my intentions on the `git` mailing list](http://article.gmane.org/gmane.comp.version-control.git/262000). + +Again in May 2018 I took advantage of another Hack Week to package +`git-deps` properly as a Python module in order to improve the +installation process. This was in preparation for demonstrating the +software at [a Meetup +event](https://www.meetup.com/londongit/events/248694943/) of the [Git +London User Group](https://www.meetup.com/londongit/). @@ -9,8 +9,31 @@ a screencast demonstration: [![YouTube screencast](./images/youtube-thumbnail.png)](http://youtu.be/irQ5gMMz-gE) -I also spoke about the tool in -[episode #32 of the GitMinutes podcast](http://episodes.gitminutes.com/2015/03/gitminutes-32-adam-spiers-on-git-deps.html). +I have also publically spoken about the tool several times: + +- [episode #32 of the GitMinutes podcast in 2015](http://episodes.gitminutes.com/2015/03/gitminutes-32-adam-spiers-on-git-deps.html) +- [a presentation I gave at the London Git User Meetup in May 2018](https://aspiers.github.io/london-git-automagic-may-2018/) +- [a presentation I gave at the OpenStack PTG in Denver, Sept 2018](https://aspiers.github.io/denver-git-automagic-sept-2018/) + + +Contents +-------- + +- [Background theory](#background-theory) +- [Motivation](#motivation) + - [Use case 1: porting between branches](USE-CASES.md#use-case-1-porting-between-branches) + - [Use case 2: splitting a patch series into independent topics](USE-CASES.md#use-case-2-splitting-a-patch-series-into-independent-topics) + - [Use case 3: aiding collaborative communication](USE-CASES.md#use-case-3-aiding-collaborative-communication) + - [Use case 4: automatic squashing of fixup commits](USE-CASES.md#use-case-4-automatic-squashing-of-fixup-commits) + - [Use case 5: rewriting commit history](USE-CASES.md#use-case-5-rewriting-commit-history) +- [Installation](INSTALL.md) +- [Usage](USAGE.md) +- [Textual vs. semantic (in)dependence](#textual-vs-semantic-independence) +- [Development / support / feedback](#development--support--feedback) +- [History](HISTORY.md) +- [Credits](#credits) +- [License](#license) + Background theory ----------------- @@ -40,134 +63,24 @@ As with many dependency relationships, these dependencies form edges in a DAG (directed acyclic graph) whose nodes correspond to commits. Note that a node can only depend on a subset of its ancestors. -Motivation ----------- - -Sometimes it is useful to understand the nature of parts of this DAG, -as its nature will impact the success or failure of operations -including merge, rebase, cherry-pick etc. - -### Use case 1: porting between branches - -For example when porting a commit "A" between git branches via `git -cherry-pick`, it can be useful to programmatically determine in advance -the minimum number of other dependent commits which would also need to -be cherry-picked to provide the context for commit "A" to cleanly -apply. Here's a quick demo! - -[![YouTube porting screencast](./images/youtube-porting-thumbnail.png)](http://youtu.be/DVksJMXxVIM) - -### Use case 2: splitting a patch series - -Large patch series or pull requests can be quite daunting for project -maintainers, since they are hard to conquer in one sitting. For this -reason it's generally best to keep the number of commits in any -submission reasonably small. However during normal hacking, you might -accumulate a large number of patches before you start to contemplate -submitting any of them upstream. In this case, `git-deps` can help -you determine how to break them up into smaller chunks. Simply run - - git deps -e $upstream_branch -s - -and then create a graph starting from the head of your local -development branch, recursively expanding all the dependencies. This -will allow you to untangle things and expose subgraphs which can be -cleanly split off into separate patch series or pull requests for -submission. +### Caveat -### Use case 3: aiding collaborative communication +It is important to be aware that any dependency graph inferred by +`git-deps` may be semantically incomplete; for example it would not +auto-detect dependencies between a commit A which changes code and +another commit B which changes documentation or tests to reflect the +code changes in commit A. Therefore `git-deps` should not be used +with blind faith. For more details, see [the section on Textual +vs. semantic (in)dependence](#textual-vs-semantic-independence) below. -Another use case might be to better understand levels of specialism / -cross-functionality within an agile team. If I author a commit which -modifies (say) lines 34-37 and 102-109 of a file, the authors of the -dependent commits are people I should potentially consider asking to -review my commit, since I'm effectively changing "their" code. -Monitoring those relationships over time might shed some light on how -agile teams should best coordinate efforts on shared code bases. -### Caveat +Motivation +---------- -Note the dependency graph is likely to be semantically incomplete; for -example it would not auto-detect dependencies between a commit A which -changes code and another commit B which changes documentation or tests -to reflect the code changes in commit A. (Although of course it's -usually best practice to either logically group such changes together -in a single commit, or use an alternate meta-history grouping -mechanism such as -[`git-dendrify`](https://github.com/bennorth/git-dendrify).) But -this should not stop it from being useful. - -### Use case 4: automatic squashing of fixup commits - -It is often desirable to amend an existing commit which is in the -current branch but not at its head. This can be done by creating a -new commit which amends (only) the existing commit, and then use `git -rebase --interactive` in order to squash the two commits together into -a new one which reuses the commit message from the original. -`git-commit[1]` has a nice feature which makes this process convenient -even when the commit to be amended is not at the head of the current -branch. It is described in [the `git-commit[1]` man -page](https://git-scm.com/docs/git-commit): - -> `--fixup=<commit>` -> -> Construct a commit message for use with `rebase --autosquash`. The -> commit message will be the subject line from the specified commit -> with a prefix of `"fixup! "`. See `git-rebase[1]` for details. - -The corresponding details in the [`git-rebase[1]` man -page](https://git-scm.com/docs/git-rebase) are: - -> `--autosquash, --no-autosquash` -> -> When the commit log message begins with `"squash! ..."` (or `"fixup! -> ..."`), and there is already a commit in the todo list that matches -> the same ..., automatically modify the todo list of `rebase -i` so -> that the commit marked for squashing comes right after the commit to -> be modified, and change the action of the moved commit from pick to -> squash (or fixup). A commit matches the ... if the commit subject -> matches, or if the ... refers to the commit’s hash. As a fall-back, -> partial matches of the commit subject work, too. The recommended way -> to create fixup/squash commits is by using the `--fixup`/`--squash` -> options of `git-commit(1)` - -However, this process still requires manually determining which commit -should be passed to the `--fixup` option. Fortunately `git-deps` can -automate this for us. To eliminate this extra work, this repository -provides a simple script which wraps around `git-deps` to automate the -whole process. First the user should ensure that any desired -amendments to the existing commit are staged in git's index. Then -they can run the `git-fixup` script which performs the following -steps: - -1. These staged amendments to existing commit are committed using - temporary commit message. - -2. `git deps HEAD^!` is run to determine which previously existing - commit this new commit is intended to "patch". This should only - result in a single dependency, otherwise the script aborts with an - error. - -3. The temporary commit's message is amended into the correct `fixup` - form. On the next `git rebase --interactive` which includes the - original commit to be amended, `git-rebase` will automatically set - up the sequencer to apply the amendment (fixup) into the original. - -In the future, this script could be extended to optionally run the -interactive `rebase`, so that the whole amendment process is taken -care of by `git-fixup`. - -### Other uses - -I'm sure there are other use cases I haven't yet thought of. If you -have any good ideas, [please submit them](CONTRIBUTING.md)! - -### Non-use cases - -At first I thought that `git-deps` might provide a useful way to -programmatically predict whether operations such as merge / rebase / -cherry-pick would succeed, but actually it's probably cheaper and more -reliable simply to perform the operation and then roll back. +Sometimes it is useful to understand the nature of parts of this +dependency graph, as its nature will impact the success or failure of +operations including merge, rebase, cherry-pick etc. Please see [the +`USE-CASES.md` file](INSTALL.md) for more details. Installation @@ -175,105 +88,97 @@ Installation Please see [the `INSTALL.md` file](INSTALL.md). + Usage ----- -Usage is fairly self-explanatory if you run `git deps -h`: - -``` -usage: git-deps [options] COMMIT-ISH [COMMIT-ISH...] - -Auto-detects commits on which the given commit(s) depend. - -optional arguments: - -h, --help Show this help message and exit - -v, --version show program's version number and exit - -l, --log Show commit logs for calculated dependencies - -j, --json Output dependencies as JSON - -s, --serve Run a web server for visualizing the dependency graph - -b IP, --bind-ip IP IP address for webserver to bind to [127.0.0.1] - -p PORT, --port PORT Port number for webserver [5000] - -r, --recurse Follow dependencies recursively - -e COMMITISH, --exclude-commits COMMITISH - Exclude commits which are ancestors of the given COMMITISH (can be repeated) - -c NUM, --context-lines NUM - Number of lines of diff context to use [1] - -d, --debug Show debugging -``` - -Currently you should run it from the root (i.e. top directory) of the -git repository you want to examine; this is a -[known limitation](https://github.com/aspiers/git-deps/issues/27). - -By default it will output the SHA1s of all dependencies of the given -commit-ish(s), one per line. With `--recurse`, it will traverse -dependencies of dependencies, and so on until it cannot find any more. -In recursion mode, two SHA1s are output per line, indicating that the -first depends on the second. - -### Web UI for visualizing and navigating the dependency graph - -If you run it with the `--serve` option and no COMMIT-ISH parameters, -then it will start a lightweight webserver and output a URL you can -connect to for dynamically visualizing and navigating the dependency -graph. - -Optionally choose a commit-ish (the form defaults to `master`), click -the `Submit` button, and you should see a graph appear with one node -per commit. By hovering the mouse over a node you will see more -details, and a little `+` icon will appear which can be clicked to -calculate dependencies of that commit, further growing the dependency -tree. You can zoom in and out with the mousewheel, and drag the -background to pan around. - -If you set up a MIME handler for the `gitfile://` protocol during -setup, [as documented](INSTALL.md) you will be able to double-click on -nodes to launch a viewer to inspect individual commits in more detail. +Please see [the `USAGE.md` file](USAGE.md). + + +Textual vs. semantic (in)dependence +----------------------------------- + +Astute readers will note that textual independence as detected by +`git-deps` is not the same as semantic / logical independence. +Textual independence means that the changes can be applied in any +order without incurring conflicts, but this is not a reliable +indicator of logical independence. + +For example a change to a function and corresponding changes to the +tests and/or documentation for that function would typically exist in +different files. So if those changes were in separate commits within +a branch, running `git-deps` on the commits would not detect any +dependency between them even though they are logically related, +because changes in different files (or even in different areas of the +same files) are textually independent. + +So in this case, `git-deps` would not behave exactly how we might +want. And for as long as AI is an unsolved problem, it is very +unlikely that it will ever develop totally reliable behaviour. So +does that mean `git-deps` is useless? Absolutely not! + +Firstly, when [best +practices](https://crealytics.com/blog/5-reasons-keeping-git-commits-small/) +for [commit +structuring](https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes) +are adhered to, changes which are strongly logically related should be +placed within the same commit anyway. So in the example above, a +change to a function and corresponding changes to the tests and/or +documentation for that function should all be within a single commit. +(Although this is not the only valid approach; for a more advanced +meta-history grouping mechanism, see +[`git-dendrify`](https://github.com/bennorth/git-dendrify).) + +Secondly, whilst textual independence does not imply logical +independence, the converse is expected to be more commonly true: +logical independence often implies textual independence (or stated +another way, textual dependence often implies logical dependence). So +while it might not be too uncommon for `git-deps` to fail to detect +the dependency between logically-related changes, it should be rarer +that it incorrectly infers a dependency between logically unrelated +changes. In other words, its false negatives are generally expected +to be more common than its false positives. As a result it is likely +to be more useful in determining a lower bound on dependencies than an +upper bound. Having said that, more research is needed on this. + +Thirdly, it is often unhelpful to allow [the quest for the perfect +become the enemy of the +good](https://en.wikipedia.org/wiki/Perfect_is_the_enemy_of_good) - a +tool does not have to be perfect to be useful; it only has to be +better than performing the same task without the tool. + +Further discussion on some of these points can be found in [an old +thread from the git mailing +list](https://public-inbox.org/git/20160528112417.GD11256@pacific.linksys.moosehall/). + +Ultimately though, ["the proof is in the +pudding"](https://en.wiktionary.org/wiki/the_proof_is_in_the_pudding), +so try it out and see! + Development / support / feedback -------------------------------- -Please see [the CONTRIBUTING file](CONTRIBUTING.md). +Please see [the `CONTRIBUTING.md` file](CONTRIBUTING.md). + History ------- -This tool was born from experiences at -[SUSEcon](http://www.susecon.com/) 2013, when I attempted to help a -colleague backport a bugfix in [OpenStack](http://www.openstack.org/) -[Nova](http://docs.openstack.org/developer/nova/) from the `master` -branch to a stable release branch. At first sight it looked like it -would only require a trivial `git cherry-pick`, but that immediately -revealed conflicts due to related code having changed in `master` -since the release was made. I manually found the underlying commit -which the bugfix required by using `git blame`, and tried another -`cherry-pick`. The same thing happened again. Very soon I found -myself in a quagmire of dependencies between commits, with no idea -whether the end was in sight. - -In coffee breaks during the ensuing openSUSE conference at the same -venue, I feverishly hacked together a prototype and it seemed to work. -Then normal life intervened, and no progress was made for another -year. - -Thanks to SUSE's generous [Hack Week](https://hackweek.suse.com/) -policy, I had the luxury of being able to spending some of early -January 2015 working to bring this tool to the next level. I -submitted a -[Hack Week project page](https://hackweek.suse.com/11/projects/366) -and -[announced my intentions on the `git` mailing list](http://article.gmane.org/gmane.comp.version-control.git/262000). - -Again in May 2018 I took advantage of another Hack Week to package -`git-deps` properly as a Python module in order to improve the -installation process. This was in preparation for demonstrating the -software at [a Meetup -event](https://www.meetup.com/londongit/events/248694943/) of the [Git -London User Group](https://www.meetup.com/londongit/). +Please see [the `HISTORY.md` file](HISTORY.md). + + +Credits +------ + +Special thanks to [SUSE](https://suse.com) for partially sponsoring +the development of this software. Thanks also to everyone who has +contributed code, bug reports, and other feedback. + License ------- -Released under [GPL version 2](COPYING) in order to be consistent with +Released under [GPL version 2](LICENSE.txt) in order to be consistent with [`git`'s license](https://github.com/git/git/blob/master/COPYING), but I'm open to the idea of dual-licensing if there's a convincing reason. diff --git a/USAGE.md b/USAGE.md new file mode 100644 index 0000000..6617bbc --- /dev/null +++ b/USAGE.md @@ -0,0 +1,56 @@ +How to use `git-deps` +======================= + +Usage is fairly self-explanatory if you run `git deps -h`: + +``` +usage: git-deps [options] COMMIT-ISH [COMMIT-ISH...] + +Auto-detects commits on which the given commit(s) depend. + +optional arguments: + -h, --help Show this help message and exit + -v, --version show program's version number and exit + -l, --log Show commit logs for calculated dependencies + -j, --json Output dependencies as JSON + -s, --serve Run a web server for visualizing the dependency graph + -b IP, --bind-ip IP IP address for webserver to bind to [127.0.0.1] + -p PORT, --port PORT Port number for webserver [5000] + -r, --recurse Follow dependencies recursively + -e COMMITISH, --exclude-commits COMMITISH + Exclude commits which are ancestors of the given COMMITISH (can be repeated) + -c NUM, --context-lines NUM + Number of lines of diff context to use [1] + -d, --debug Show debugging +``` + +Currently you should run it from the root (i.e. top directory) of the +git repository you want to examine; this is a +[known limitation](https://github.com/aspiers/git-deps/issues/27). + +By default it will output the SHA1s of all dependencies of the given +commit-ish(s), one per line. With `--recurse`, it will traverse +dependencies of dependencies, and so on until it cannot find any more. +In recursion mode, two SHA1s are output per line, indicating that the +first depends on the second. + + +Web UI for visualizing and navigating the dependency graph +---------------------------------------------------------- + +If you run it with the `--serve` option and no COMMIT-ISH parameters, +then it will start a lightweight webserver and output a URL you can +connect to for dynamically visualizing and navigating the dependency +graph. + +Optionally choose a commit-ish (the form defaults to `master`), click +the `Submit` button, and you should see a graph appear with one node +per commit. By hovering the mouse over a node you will see more +details, and a little `+` icon will appear which can be clicked to +calculate dependencies of that commit, further growing the dependency +tree. You can zoom in and out with the mousewheel, and drag the +background to pan around. + +If you set up a MIME handler for the `gitfile://` protocol during +setup, [as documented](INSTALL.md) you will be able to double-click on +nodes to launch a viewer to inspect individual commits in more detail. diff --git a/USE-CASES.md b/USE-CASES.md new file mode 100644 index 0000000..40b87a5 --- /dev/null +++ b/USE-CASES.md @@ -0,0 +1,154 @@ +`git-deps` use cases +====================== + +Several use cases for `git-deps` are listed in detail below. They are +also [mentioned in the presentation I gave in September +2018](https://aspiers.github.io/denver-git-automagic-sept-2018/#/git-deps-motivation) +(see also [the video](https://youtu.be/f6anrSKCIgI?t=216)). + +- [Use case 1: porting between branches](#use-case-1-porting-between-branches) +- [Use case 2: splitting a patch series into independent topics](#use-case-2-splitting-a-patch-series-into-independent-topics) +- [Use case 3: aiding collaborative communication](#use-case-3-aiding-collaborative-communication) +- [Use case 4: automatic squashing of fixup commits](#use-case-4-automatic-squashing-of-fixup-commits) +- [Use case 5: rewriting commit history](#use-case-5-rewriting-commit-history) + +### Use case 1: porting between branches + +For example when porting a commit "A" between git branches via `git +cherry-pick`, it can be useful to programmatically determine in advance +the minimum number of other dependent commits which would also need to +be cherry-picked to provide the context for commit "A" to cleanly +apply. Here's a quick demo! + +[![YouTube porting screencast](./images/youtube-porting-thumbnail.png)](http://youtu.be/DVksJMXxVIM) + +**CAVEAT**: `git-deps` is not AI and only does a textual dependency +analysis, therefore it does not guarantee there is no simpler way to +backport. It also may infer more dependencies than strictly necessary +due the default setting of one line of fuzz (diff context). Shrinking +this to zero lines may produce a more conservative dependency tree, +but it's also riskier and more likely to cause conflicts or even bad +code on cherry-pick. git-deps just provides a first estimate. + +Therefore combining it with human analysis of the commits in the +dependency tree is strongly recommended. This may reveal +opportunities for selective pruning or other editing of commits during +the backport process which may be able to reduce the number of commits +which are required. + +### Use case 2: splitting a patch series into independent topics + +Large patch series or pull requests can be quite daunting for project +maintainers, since they are hard to conquer in one sitting. For this +reason it's generally best to keep the number of commits in any +submission reasonably small. However during normal hacking, you might +accumulate a large number of patches before you start to contemplate +submitting any of them upstream. In this case, `git-deps` can help +you determine how to break them up into smaller chunks. Simply run + + git deps -e $upstream_branch -s + +and then create a graph starting from the head of your local +development branch, recursively expanding all the dependencies. This +will allow you to untangle things and expose subgraphs which can be +cleanly split off into separate patch series or pull requests for +submission. + +In fact this technique is sufficiently useful but tedious to do +manually that I wrote a whole separate tool +[`git-explode`](https://github.com/aspiers/git-explode) to automate +the process. It uses `git-deps` as a library module behind the scenes +for the dependency inference. See [the +`README`](https://github.com/aspiers/git-explode/blob/master/README.rst) +for more details. + +### Use case 3: aiding collaborative communication + +Another use case might be to better understand levels of specialism / +cross-functionality within an agile team. If I author a commit which +modifies (say) lines 34-37 and 102-109 of a file, the authors of the +dependent commits are people I should potentially consider asking to +review my commit, since I'm effectively changing "their" code. +Monitoring those relationships over time might shed some light on how +agile teams should best coordinate efforts on shared code bases. + +### Use case 4: automatic squashing of fixup commits + +It is often desirable to amend an existing commit which is in the +current branch but not at its head. This can be done by creating a +new commit which amends (only) the existing commit, and then use `git +rebase --interactive` in order to squash the two commits together into +a new one which reuses the commit message from the original. +`git-commit[1]` has a nice feature which makes this process convenient +even when the commit to be amended is not at the head of the current +branch. It is described in [the `git-commit[1]` man +page](https://git-scm.com/docs/git-commit): + +> `--fixup=<commit>` +> +> Construct a commit message for use with `rebase --autosquash`. The +> commit message will be the subject line from the specified commit +> with a prefix of `"fixup! "`. See `git-rebase[1]` for details. + +The corresponding details in the [`git-rebase[1]` man +page](https://git-scm.com/docs/git-rebase) are: + +> `--autosquash, --no-autosquash` +> +> When the commit log message begins with `"squash! ..."` (or `"fixup! +> ..."`), and there is already a commit in the todo list that matches +> the same ..., automatically modify the todo list of `rebase -i` so +> that the commit marked for squashing comes right after the commit to +> be modified, and change the action of the moved commit from pick to +> squash (or fixup). A commit matches the ... if the commit subject +> matches, or if the ... refers to the commit’s hash. As a fall-back, +> partial matches of the commit subject work, too. The recommended way +> to create fixup/squash commits is by using the `--fixup`/`--squash` +> options of `git-commit(1)` + +However, this process still requires manually determining which commit +should be passed to the `--fixup` option. Fortunately `git-deps` can +automate this for us. To eliminate this extra work, this repository +provides a simple script which wraps around `git-deps` to automate the +whole process. First the user should ensure that any desired +amendments to the existing commit are staged in git's index. Then +they can run the `git-fixup` script which performs the following +steps: + +1. These staged amendments to existing commit are committed using + temporary commit message. + +2. `git deps HEAD^!` is run to determine which previously existing + commit this new commit is intended to "patch". This should only + result in a single dependency, otherwise the script aborts with an + error. + +3. The temporary commit's message is amended into the correct `fixup` + form. On the next `git rebase --interactive` which includes the + original commit to be amended, `git-rebase` will automatically set + up the sequencer to apply the amendment (fixup) into the original. + +In the future, this script could be extended to optionally run the +interactive `rebase`, so that the whole amendment process is taken +care of by `git-fixup`. + +### Use case 5: rewriting commit history + +It is often useful to reorder or rewrite commit history within private +branches, as part of a history polishing process which ensures that +eventually published history is of a high quality (see ["On Sausage +Making"](https://sethrobertson.github.io/GitBestPractices/#sausage)). + +However reordering or removing commits can cause conflicts. Whilst +`git-deps` can programmatically predict whether operations such as +merge / rebase / cherry-pick would succeed, actually it's probably +cheaper and more reliable simply to perform the operation and then +roll back. However `git-deps` could be used to detect ways to avoid +these conflicts, for example reordering or removing a commit's +dependencies along with the commit itself. In the future tools could +be built on top of `git-deps` to automate these processes. + +### Other uses + +I'm sure there are other use cases I haven't yet thought of. If you +have any good ideas, [please submit them](CONTRIBUTING.md)! |