Answers: <p>Assuming I'm understanding you correctly, there's a much simpler way to do this.  If you know the path to the file(s) that you need within the git repo, you can use <code>git archive</code>.  This fetches a single file directly from a remote repository, so it always grabs the latest version.  I've used this a few times from within a Jenkins Pipeline script.  For instance:</p>
  <pre><code>def cmd = &quot;git archive --remote='${repoUrl}' '${ref}' '${fileName}' | tar -xO&quot;
  sh(cmd)
  </code></pre>
  <p>In this example, <code>repoUrl</code> is the remote URL of the git repo, <code>$ref</code> is the ref (tag or branch) to fetch, and <code>fileName</code> is the file to fetch from the repository.  If you need more than one file, you can list each one as a separate argument to <code>git archive</code>.</p>
  <p>Note that if you're running this from a Pipeline script, you may need to wrap it in <code>withCredentials</code> in order to set up the proper SSH keys or username/password credentials for your git repo.</p>
  
Answers: CC BY-SA 4.0
Answers: 2021-06-01T15:59:56.523Z
Answers: 2021-06-01T15:59:56.523Z
Answers: jayhendren
Body: <p>We have a huge ~20GB monorepo. For a particular Jenkins job, we do not need to clone the entire repo but only need a few sub-directories.
  The solution for this is of course <a href="https://stackoverflow.com/questions/10791472/jenkins-and-git-sparse-checkouts">git sparse checkout</a>. However this is quiet cumbersome to set up and maintain. You probably have to run the job a few times to make sure you did not miss any directory. Also, in the future if you added a dependency (inside another directory) that was not in the sparse checkout list, you have to remember to add it back.</p>
  <p>What if we can improve this process?</p>
  <ol>
  <li>We should be able to identify all the scripts that a particular Jenkins job needs by looking into a<a href="https://en.wikipedia.org/wiki/Open_(system_call)#:%7E:text=For%20most%20file%20systems%2C%20a,performed%20by%20the%20first%20access." rel="nofollow noreferrer">ll the files that the OS has opened</a> inside that job's working directory.</li>
  <li>We already have tools like <code>lsof</code>, <code>sysdig</code>, <code>opensnoop</code> which can show us all files that are open inside a directory.</li>
  <li>On the first ever run of the Jenkins job, we clone the entire repo.</li>
  <li>Then we start <code>lsof +D /job/workspace</code> and monitor which files got opened.</li>
  <li>At the end of the job we create a data structure like <code>{JOB_NAME: [list, of, files]}</code> and save it somewhere.</li>
  <li>Rerun the job ~5 times to ensure data correctness.</li>
  <li>On all subsequent runs, the git clone command will parse above file and only <code>sparse-checkout</code> the required files.</li>
  <li>If in the future, the job fails due to a <code>FileNotFound</code> error, we can infer that a new dependency was added, add that new dependency and re-run the job.</li>
  </ol>
  <p>Wanted to run the viability of this idea with the DevOps Community.</p>
  
Tags: <jenkins><git>
Title: Jenkins: Dynamically git clone only the files required for a particular job from a monorepo
UserDisplayName: Gh0sT
ThreadText: # Jenkins: Dynamically git clone only the files required for a particular job from a monorepo
  
  (Asked by: username_0 on 2021-06-01)
  
  We have a huge ~20GB monorepo. For a particular Jenkins job, we do not need to clone the entire repo but only need a few sub-directories.
  The solution for this is of course [git sparse checkout](https://stackoverflow.com/questions/10791472/jenkins-and-git-sparse-checkouts). However this is quiet cumbersome to set up and maintain. You probably have to run the job a few times to make sure you did not miss any directory. Also, in the future if you added a dependency (inside another directory) that was not in the sparse checkout list, you have to remember to add it back.
  
  What if we can improve this process?
  
  1. We should be able to identify all the scripts that a particular Jenkins job needs by looking into a[ll the files that the OS has opened](https://en.wikipedia.org/wiki/Open_(system_call)#:%7E:text=For%20most%20file%20systems%2C%20a,performed%20by%20the%20first%20access.) inside that job's working directory.
  2. We already have tools like `lsof`, `sysdig`, `opensnoop` which can show us all files that are open inside a directory.
  3. On the first ever run of the Jenkins job, we clone the entire repo.
  4. Then we start `lsof +D /job/workspace` and monitor which files got opened.
  5. At the end of the job we create a data structure like `{JOB_NAME: [list, of, files]}` and save it somewhere.
  6. Rerun the job ~5 times to ensure data correctness.
  7. On all subsequent runs, the git clone command will parse above file and only `sparse-checkout` the required files.
  8. If in the future, the job fails due to a `FileNotFound` error, we can infer that a new dependency was added, add that new dependency and re-run the job.
  
  Wanted to run the viability of this idea with the DevOps Community.
  
  **Tags:** jenkins, git
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-06-01. Score: 1
  
  Assuming I'm understanding you correctly, there's a much simpler way to do this. If you know the path to the file(s) that you need within the git repo, you can use `git archive`. This fetches a single file directly from a remote repository, so it always grabs the latest version. I've used this a few times from within a Jenkins Pipeline script. For instance:
  
  ```
  def cmd = "git archive --remote='${repoUrl}' '${ref}' '${fileName}' | tar -xO"
  sh(cmd)
  
  ```
  
  In this example, `repoUrl` is the remote URL of the git repo, `$ref` is the ref (tag or branch) to fetch, and `fileName` is the file to fetch from the repository. If you need more than one file, you can list each one as a separate argument to `git archive`.
  
  Note that if you're running this from a Pipeline script, you may need to wrap it in `withCredentials` in order to set up the proper SSH keys or username/password credentials for your git repo.
  
  
  ---
  
  