{ "info": { "author": "Adam Spiers", "author_email": "git@adamspiers.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Console", "Environment :: Web Environment", "Framework :: Flask", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Version Control", "Topic :: Utilities" ], "description": "|Code Climate|\n\ngit-deps\n========\n\n``git-deps`` is a tool for performing automatic analysis of dependencies\nbetween commits in a `git `__ repository. Here\u2019s a\nscreencast demonstration:\n\n|YouTube screencast|\n\nI also spoke about the tool in `episode #32 of the GitMinutes\npodcast `__.\n\nBackground theory\n-----------------\n\nIt is fairly clear that two git commits within a single repo can be\nconsidered \u201cindependent\u201d from each other in a certain sense, if they do\nnot change the same files, or if they do not change overlapping parts of\nthe same file(s).\n\nIn contrast, when a commit changes a line, it is \u201cdependent\u201d on not only\nthe commit which last changed that line, but also any commits which were\nresponsible for providing the surrounding lines of context, because\nwithout those previous versions of the line and its context, the\ncommit\u2019s diff might not cleanly apply (depending on how it\u2019s being\napplied, of course). So all dependencies of a commit can be\nprogrammatically inferred by running git-blame on the lines the commit\nchanges, plus however many lines of context make sense for the use case\nof this particular dependency analysis.\n\nTherefore the dependency calculation is impacted by a \u201cfuzz\u201d factor\nparameter (c.f.\n`patch(1) `__), i.e.\u00a0the\nnumber of lines of context which are considered necessary for the\ncommit\u2019s diff to cleanly apply.\n\nAs with many dependency relationships, these dependencies form edges in\na DAG (directed acyclic graph) whose nodes correspond to commits. Note\nthat a node can only depend on a subset of its ancestors.\n\nMotivation\n----------\n\nSometimes it is useful to understand the nature of parts of this DAG, as\nits nature will impact the success or failure of operations including\nmerge, rebase, cherry-pick etc.\n\nUse case 1: porting between branches\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFor example when porting a commit \u201cA\u201d between git branches via\n``git cherry-pick``, it can be useful to programmatically determine in\nadvance the minimum number of other dependent commits which would also\nneed to be cherry-picked to provide the context for commit \u201cA\u201d to\ncleanly apply. Here\u2019s a quick demo!\n\n|YouTube porting screencast|\n\nUse case 2: splitting a patch series\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nLarge patch series or pull requests can be quite daunting for project\nmaintainers, since they are hard to conquer in one sitting. For this\nreason it\u2019s generally best to keep the number of commits in any\nsubmission reasonably small. However during normal hacking, you might\naccumulate a large number of patches before you start to contemplate\nsubmitting any of them upstream. In this case, ``git-deps`` can help you\ndetermine how to break them up into smaller chunks. Simply run\n\n::\n\n git deps -e $upstream_branch -s\n\nand then create a graph starting from the head of your local development\nbranch, recursively expanding all the dependencies. This will allow you\nto untangle things and expose subgraphs which can be cleanly split off\ninto separate patch series or pull requests for submission.\n\nUse case 3: aiding collaborative communication\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAnother use case might be to better understand levels of specialism /\ncross-functionality within an agile team. If I author a commit which\nmodifies (say) lines 34-37 and 102-109 of a file, the authors of the\ndependent commits forms a list which indicates the group of people I\nshould potentially consider asking to review my commit, since I\u2019m\neffectively changing \u201ctheir\u201d code. Monitoring those relationships over\ntime might shed some light on how agile teams should best coordinate\nefforts on shared code bases.\n\nCaveat\n~~~~~~\n\nNote the dependency graph is likely to be semantically incomplete; for\nexample it would not auto-detect dependencies between a commit A which\nchanges code and another commit B which changes documentation or tests\nto reflect the code changes in commit A. (Although of course it\u2019s\nusually best practice to logically group such changes together in a\nsingle commit.) But this should not stop it from being useful.\n\nOther uses\n~~~~~~~~~~\n\nI\u2019m sure there are other use cases I haven\u2019t yet thought of. If you have\nany good ideas, `please submit them `__!\n\nNon-use cases\n~~~~~~~~~~~~~\n\nAt first I thought that ``git-deps`` might provide a useful way to\nprogrammatically predict whether operations such as merge / rebase /\ncherry-pick would succeed, but actually it\u2019s probably cheaper and more\nreliable simply to perform the operation and then roll back.\n\nInstallation\n------------\n\nPlease see `the ``INSTALL.md`` file `__.\n\nUsage\n-----\n\nThe tool is not yet fully documented, but usage is fairly\nself-explanatory if you run ``git deps -h``.\n\nCurrently you should run it from the root (i.e.\u00a0top directory) of the\ngit repository you want to examine; this is a `known\nlimitation `__.\n\nBy default it will output all dependencies of the given commit-ish(s),\none per line. With ``--recurse``, it will traverse dependencies of\ndependencies, and so on until it cannot find any more. In recursion\nmode, two SHA1s are output per line, indicating that the first depends\non the second.\n\nWeb UI for visualizing and navigating the dependency graph\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you run with the ``--serve`` option then it will start a lightweight\nwebserver and output a URL you can connect to for dynamically\nvisualizing and navigating the dependency graph.\n\nOptionally choose a commit-ish (the form defaults to ``master``), click\nthe ``Submit`` button, and you should see a graph appear with one node\nper commit. By hovering the mouse over a node you will see more details,\nand a little ``+`` icon will appear which can be clicked to calculate\ndependencies of that commit, further growing the dependency tree. You\ncan zoom in and out with the mousewheel, and drag the background to pan\naround.\n\nIf you set up a MIME handler for the ``gitfile://`` protocol during\nsetup, `as documented `__ you will be able to double-click\non nodes to launch a viewer to inspect individual commits in more\ndetail.\n\nDevelopment / support / feedback\n--------------------------------\n\nPlease see `the CONTRIBUTING file `__.\n\nHistory\n-------\n\nThis tool was born from experiences at\n`SUSEcon `__ 2013, when I attempted to help a\ncolleague backport a bugfix in `OpenStack `__\n`Nova `__ from the ``master``\nbranch to a stable release branch. At first sight it looked like it\nwould only require a trivial ``git cherry-pick``, but that immediately\nrevealed conflicts due to related code having changed in ``master``\nsince the release was made. I manually found the underlying commit which\nthe bugfix required by using ``git blame``, and tried another\n``cherry-pick``. The same thing happened again. Very soon I found myself\nin a quagmire of dependencies between commits, with no idea whether the\nend was in sight.\n\nIn coffee breaks during the ensuing openSUSE conference at the same\nvenue, I feverishly hacked together a prototype and it seemed to work.\nThen normal life intervened, and no progress was made for another year.\n\nThanks to SUSE\u2019s generous `Hack Week `__\npolicy, I had the luxury of being able to spending some of early January\n2015 working to bring this tool to the next level. I submitted a `Hack\nWeek project page `__ and\n`announced my intentions on the ``git`` mailing\nlist `__.\n\nAgain in May 2018 I took advantage of another Hack Week to package\n``git-deps`` properly as a Python module in order to improve the\ninstallation process. This was in preparation for demonstrating the\nsoftware at `a Meetup\nevent `__ of the\n`Git London User Group `__.\n\nLicense\n-------\n\nReleased under `GPL version 2 `__ in order to be consistent\nwith ```git``\\ \u2019s\nlicense `__, but I\u2019m\nopen to the idea of dual-licensing if there\u2019s a convincing reason.\n\n.. |Code Climate| image:: https://codeclimate.com/github/aspiers/git-deps/badges/gpa.svg\n :target: https://codeclimate.com/github/aspiers/git-deps\n.. |YouTube screencast| image:: ./images/youtube-thumbnail.png\n :target: http://youtu.be/irQ5gMMz-gE\n.. |YouTube porting screencast| image:: ./images/youtube-porting-thumbnail.png\n :target: http://youtu.be/DVksJMXxVIM", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aspiers/git-deps", "keywords": "", "license": "GPL-2+", "maintainer": "", "maintainer_email": "", "name": "git-deps", "package_url": "https://pypi.org/project/git-deps/", "platform": "", "project_url": "https://pypi.org/project/git-deps/", "project_urls": { "Homepage": "https://github.com/aspiers/git-deps" }, "release_url": "https://pypi.org/project/git-deps/1.0.1/", "requires_dist": null, "requires_python": "", "summary": "automatically detect dependencies between git commits", "version": "1.0.1" }, "last_serial": 3870410, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "4961957c125ad4a2eb778a0113deda86", "sha256": "979151c82fd2e08bdef60f34a0fc0919534883e9e29ac3eee2ff63b593532d4d" }, "downloads": -1, "filename": "git-deps-1.0.0.tar.gz", "has_sig": false, "md5_digest": "4961957c125ad4a2eb778a0113deda86", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5356894, "upload_time": "2018-05-16T16:44:00", "url": "https://files.pythonhosted.org/packages/77/1a/925137bf7617273296924387c60ca1120e10a13587e6adcdcab7ca9df3af/git-deps-1.0.0.tar.gz" } ], "1.0.0rc1": [ { "comment_text": "", "digests": { "md5": "44b8b7bffd86219eda94a56f1f6d5324", "sha256": "3c5be4ac9b6ddd8a34ffc12ccc6a0f63d6b8f327c6bef3f9b65aa197d9b7667e" }, "downloads": -1, "filename": "git-deps-1.0.0rc1.tar.gz", "has_sig": false, "md5_digest": "44b8b7bffd86219eda94a56f1f6d5324", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12483136, "upload_time": "2018-05-16T14:06:00", "url": "https://files.pythonhosted.org/packages/15/1e/1da15cccd932612518dd38c16f458f5a78fc3b77ad12896f2255fc0be820/git-deps-1.0.0rc1.tar.gz" } ], "1.0.0rc2": [ { "comment_text": "", "digests": { "md5": "ae98794af22e671b6a339377005402d8", "sha256": "b994106739bd128f07bfdc72d97057ffb0357cc5492a13bf5f6f16f2ec29fb9b" }, "downloads": -1, "filename": "git-deps-1.0.0rc2.tar.gz", "has_sig": false, "md5_digest": "ae98794af22e671b6a339377005402d8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12483622, "upload_time": "2018-05-16T15:26:47", "url": "https://files.pythonhosted.org/packages/3c/31/946b8b1d984361cc79c383cfc52dc8bdc3ae68e59de15991a5c2340ef624/git-deps-1.0.0rc2.tar.gz" } ], "1.0.0rc3": [ { "comment_text": "", "digests": { "md5": "925bd2cbdbc6e4138bd8de4de3de9947", "sha256": "b72639b6d55c86738696d587892ca40686d2e23dc814fe0bc8d685adba528608" }, "downloads": -1, "filename": "git-deps-1.0.0rc3.tar.gz", "has_sig": false, "md5_digest": "925bd2cbdbc6e4138bd8de4de3de9947", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12483214, "upload_time": "2018-05-16T15:43:43", "url": "https://files.pythonhosted.org/packages/49/af/8255a957cc502dce9b4fb19e97198ffb479a6273d68bc2c7f3d9944623c8/git-deps-1.0.0rc3.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "36a3e6e97f332ec0a94e98455759bb4d", "sha256": "0b02e7a42da7e9931432d8b2f611e8f80d5ff61a0c2d5b0dfdb3c8e3b02442b7" }, "downloads": -1, "filename": "git-deps-1.0.1.tar.gz", "has_sig": false, "md5_digest": "36a3e6e97f332ec0a94e98455759bb4d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5710328, "upload_time": "2018-05-16T23:12:06", "url": "https://files.pythonhosted.org/packages/6d/02/b90cfd102dcd6bddaccbaed0b55d7d39cea8fa602c465fb8f35216028ea1/git-deps-1.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "36a3e6e97f332ec0a94e98455759bb4d", "sha256": "0b02e7a42da7e9931432d8b2f611e8f80d5ff61a0c2d5b0dfdb3c8e3b02442b7" }, "downloads": -1, "filename": "git-deps-1.0.1.tar.gz", "has_sig": false, "md5_digest": "36a3e6e97f332ec0a94e98455759bb4d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5710328, "upload_time": "2018-05-16T23:12:06", "url": "https://files.pythonhosted.org/packages/6d/02/b90cfd102dcd6bddaccbaed0b55d7d39cea8fa602c465fb8f35216028ea1/git-deps-1.0.1.tar.gz" } ] }