My approach:
keep my &quot;raw&quot; requirements.<i>\.txt files in a &quot;.requirements&quot; directory in the project root. The packages listed here mainly are bare, without a version qualifier. 
I run the script at <a href="https:&#x2F;&#x2F;gist.github.com&#x2F;nicois&#x2F;b49deb1f92e9f504cd93715a78440b9b" rel="nofollow">https:&#x2F;&#x2F;gist.github.com&#x2F;nicois&#x2F;b49deb1f92e9f504cd93715a78440...</a>
This creates matching requirements.</i> files in the project root, with specific python package versions for everything.
Both sets of files are checked into the repository.
Periodically, I re-run the gist, which updates the requirements in the repo.<p>IMO this is the best of both worlds: in the &quot;bare&quot; requirements I only put what I want, and the derived requirements file is a fully-defined list of what I need.<p>This means each commit in my repo is not susceptible to third-party changes: when my tests pass on a given commit, it will pass every time in the future too. I can decide when I want to refresh the requirements, and it&#x27;s a simple one-liner.