<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Andreas Augustin</title>
    <description>The latest articles on Forem by Andreas Augustin (@andreasaugustin).</description>
    <link>https://forem.com/andreasaugustin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F204027%2F5e97f562-f760-4abc-99e2-c36cba68c0f7.jpeg</url>
      <title>Forem: Andreas Augustin</title>
      <link>https://forem.com/andreasaugustin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andreasaugustin"/>
    <language>en</language>
    <item>
      <title>Git - GitHub actions-template-sync</title>
      <dc:creator>Andreas Augustin</dc:creator>
      <pubDate>Sun, 11 Dec 2022 21:12:22 +0000</pubDate>
      <link>https://forem.com/andreasaugustin/github-actions-template-sync-1g9k</link>
      <guid>https://forem.com/andreasaugustin/github-actions-template-sync-1g9k</guid>
      <description>&lt;h1&gt;
  
  
  GitHub actions-template-sync
&lt;/h1&gt;

&lt;h2&gt;
  
  
  abstract
&lt;/h2&gt;

&lt;p&gt;Sometimes we want to synchronize some git repositories. In general this is not a huge task using commands like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NEW_BRANCH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
git pull &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SOURCE_REPO&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--allow-unrelated-histories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in the target repository.&lt;br&gt;
Often there are many repositories you want to synchronize. E.q. you have created your repositories using a GitHub template repository.&lt;br&gt;
Click the links to get some more information about how to &lt;a href="https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository"&gt;create&lt;/a&gt; and &lt;a href="https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template"&gt;use&lt;/a&gt; template repositories.&lt;br&gt;
When you are making changes within the template repository often like to propagate those changes into the repositories created from the template.&lt;br&gt;
To automate this task I created a Github action &lt;a href="https://github.com/marketplace/actions/actions-template-sync"&gt;acions-template-sync&lt;/a&gt;&lt;br&gt;
Instead of looping through all repositories and execute the commands listed above you can configure the &lt;a href="https://github.com/marketplace/actions/actions-template-sync"&gt;actions-template-sync&lt;/a&gt; and receive automatically Pull requests within the target repositories.&lt;/p&gt;
&lt;h3&gt;
  
  
  Remarks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It is possible to use this GitHub action even if the source repository is not a template repository.&lt;/li&gt;
&lt;li&gt;If you are interested in the source code, please checkout the &lt;a href="https://github.com/AndreasAugustin/actions-template-sync"&gt;source code repository&lt;/a&gt;.
Contributions of any kind are welcome.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;The usage is designed to be simple. Just put a &lt;code&gt;actions_templae_sync.yaml&lt;/code&gt; definition file into your &lt;code&gt;.github/workflows/&lt;/code&gt; folder.&lt;br&gt;
Please click the following link if you want to get further information about &lt;a href="https://docs.github.com/en/actions"&gt;GitHub Actions&lt;/a&gt;.&lt;br&gt;
The content of the file should look like the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions-template-sync&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# cronjob trigger At 00:00 on day-of-month 1. https://crontab.guru/every-month&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
  &lt;span class="c1"&gt;# manual trigger&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repo-sync&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# To use this repository's private action, you must check out the repository&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions-template-sync&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AndreasAugustin/actions-template-sync@&amp;lt;replace_with_latest_version&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;github_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;source_repo_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;replace_with_source_repo_path&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;upstream_branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt; &lt;span class="c1"&gt;# defaults to main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please replace the following variables&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;replace with&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;replace_with_latest_version&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;replace with the latest &lt;a href="https://github.com/marketplace/actions/actions-template-sync"&gt;release version&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;replace_with_source_repo_path&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;replace with the path of the source repository (without the hostname)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is a base configuration used for public &lt;code&gt;github.com&lt;/code&gt; repositories. Also private and github enterprise servers are supported.&lt;br&gt;
Please have a look into the available &lt;a href="https://github.com/AndreasAugustin/actions-template-sync#configuration-parameters"&gt;configuration paraemters&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Authentication and authorization
&lt;/h2&gt;

&lt;p&gt;Currently with a public repository as a source you do not need to do any changes and the example works out of the box.&lt;br&gt;
For a private source repository currently follwoing AUTHN/AUTHZ methods are supported&lt;/p&gt;
&lt;h3&gt;
  
  
  SSH
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SSH&lt;/code&gt; is supported. Here you can find an example for the setup.&lt;/p&gt;
&lt;h4&gt;
  
  
  SSH keygen
&lt;/h4&gt;

&lt;p&gt;First you need to create an ssh key. Just use the &lt;code&gt;ssh-keygen&lt;/code&gt; command. &lt;strong&gt;Important&lt;/strong&gt; do set a password.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v45-pWLl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnqswak269vce5ukq2to.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v45-pWLl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnqswak269vce5ukq2to.gif" alt="ssh_keygen" width="880" height="472"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Private Key
&lt;/h4&gt;

&lt;p&gt;Add the private key as a secret into the target repository, e.q. with the name &lt;strong&gt;SOURCE_REPO_SSH_PRIVATE_KEY&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click &lt;em&gt;settings&lt;/em&gt; within the target repo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jqZ0-fwn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4shz9knlbopasbxtmlh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jqZ0-fwn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4shz9knlbopasbxtmlh.png" alt="target_repo_settings" width="880" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;select &lt;em&gt;Secrets -&amp;gt; Actions&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZYvSyoKd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ookiq55acbhvfjgyp777.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZYvSyoKd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ookiq55acbhvfjgyp777.png" alt="target_repo_actions_secret" width="359" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click &lt;em&gt;New repository secret&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YBISrJJc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f9gcg0yh98bg3fsnufmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YBISrJJc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f9gcg0yh98bg3fsnufmn.png" alt="target_repo_new_secret" width="880" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name the secret (e.q. &lt;strong&gt;SOURCE_REPO_SSH_PRIVATE_KEY&lt;/strong&gt;) and paste the &lt;strong&gt;private ssh key&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4ryXVhrI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmb3tc5wlko6q96h3932.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4ryXVhrI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmb3tc5wlko6q96h3932.png" alt="target_repo_private_ssh" width="794" height="453"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Public key
&lt;/h4&gt;

&lt;p&gt;Add the public key as a deployment key into the source repository.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click &lt;em&gt;settings&lt;/em&gt; within the source repository&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FcVXRKGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32acp4u2fuqd7qvzgk7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FcVXRKGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32acp4u2fuqd7qvzgk7a.png" alt="source_repo_settings" width="880" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click &lt;em&gt;deploy keys&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PILJYgiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ss20gfdp3wqoeaqgr5kp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PILJYgiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ss20gfdp3wqoeaqgr5kp.png" alt="source_repo_deployment_keys" width="333" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;click &lt;em&gt;add deploy key&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PwG-ySKL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9p0e8o4falp08718da3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PwG-ySKL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9p0e8o4falp08718da3.png" alt="source_repo_click_deploy_key" width="880" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a meaningful name. No need to add write permissions. Paste here your &lt;strong&gt;public ssh key&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tbm6mBAG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbuj0tazkxcjsoqnpk9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tbm6mBAG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbuj0tazkxcjsoqnpk9l.png" alt="source_repo_add_depl_key" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Prepare the action
&lt;/h4&gt;

&lt;p&gt;Now you need to prepare the action. Edit/create the github action config the following way&lt;/p&gt;

&lt;p&gt;As a best practice it is recommended that also the &lt;em&gt;source_repo_path&lt;/em&gt; is used in a secret.&lt;br&gt;
Create a secret like you have done before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repo-sync&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# To use this repository's private action, you must check out the repository&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions-template-sync&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AndreasAugustin/actions-template-sync@&amp;lt;replace_with_latest_version&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;github_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;source_repo_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SOURCE_REPO_PATH }}&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;owner/repo&amp;gt;, should be within secrets&lt;/span&gt;
          &lt;span class="na"&gt;source_repo_ssh_private_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SOURCE_REPO_SSH_PRIVATE_KEY }}&lt;/span&gt; &lt;span class="c1"&gt;# contains the private ssh key of the private repository&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ko-fi.com/A0A4EKB66"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>sync</category>
      <category>github</category>
    </item>
    <item>
      <title>GIT - Prevent accidentally pushing credentials</title>
      <dc:creator>Andreas Augustin</dc:creator>
      <pubDate>Sat, 27 Aug 2022 20:22:00 +0000</pubDate>
      <link>https://forem.com/andreasaugustin/git-pretend-accidentally-pushing-git-credentials-11hh</link>
      <guid>https://forem.com/andreasaugustin/git-pretend-accidentally-pushing-git-credentials-11hh</guid>
      <description>&lt;h2&gt;
  
  
  abstract
&lt;/h2&gt;

&lt;p&gt;Sometimes by accident people accidentally push credentials or other sensitive information into a git repository. For example &lt;strong&gt;AWS_SECRET_ACCESS_KEY&lt;/strong&gt; and &lt;strong&gt;AWS_ACCESS_KEY_ID&lt;/strong&gt;.&lt;br&gt;
Obviously bad people are able to find those secrets in the git repository or history using them to e.q. start cryptominers in those accounts. That leads to super high costs and bills for the poor person who accidentally pushed those secrets.&lt;br&gt;
There is a tool which can prevent you doing such mistakes: &lt;a href="https://github.com/awslabs/git-secrets"&gt;git-secrets&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Please check &lt;a href="https://github.com/awslabs/git-secrets#installing-git-secrets"&gt;git secrets installation&lt;/a&gt; for your OS. Here I show you the installation for &lt;strong&gt;Linux&lt;/strong&gt;.&lt;br&gt;
Just type the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:awslabs/git-secrets.git
&lt;span class="nb"&gt;cd &lt;/span&gt;git-secrets
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; make &lt;span class="nb"&gt;install
&lt;/span&gt;make &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--co0ogj6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqvtase4owshg3dt8grs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--co0ogj6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqvtase4owshg3dt8grs.gif" alt="install" width="880" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Remarks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For users with docker knowledge: have prepared a &lt;a href="https://hub.docker.com/repository/docker/andyaugustin/git-secrets"&gt;docker image&lt;/a&gt; where git-secret is already installed.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker run -v &amp;lt;local_git_repo&amp;gt;:/home/git-secrets/ andyaugustin/git-secrets:main git-secrets&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;For uninstallation on &lt;strong&gt;Linux&lt;/strong&gt; just remove the copied files again
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; /usr/local/bin/git-secrets
&lt;span class="nb"&gt;rm&lt;/span&gt; /usr/local/share/man/man1/git-secrets.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fun part
&lt;/h2&gt;

&lt;p&gt;Now lets check the power of git-secrets.&lt;br&gt;
Please keep in mind that you need to enable the tool for every repository. It will install &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks"&gt;git hooks&lt;/a&gt; into your &lt;strong&gt;local&lt;/strong&gt; repository.&lt;/p&gt;

&lt;p&gt;For the turorial we will init a git repo first and bootstrap &lt;strong&gt;git-secrets&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;git-secrets-example
&lt;span class="nb"&gt;cd &lt;/span&gt;git-secrets-example
git init
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# git-secrets-example"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-S&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"doc(): initial commit :star:"&lt;/span&gt;
git-secrets &lt;span class="nt"&gt;--install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As stated in the output we got 3 new files added into our local git repository. Those will prevent us to accidentally commit secrets to the git database. Lets check one of those files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; .git/hooks/pre-commit
&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
git secrets &lt;span class="nt"&gt;--pre_commit_hook&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This hook will be run every time in the &lt;strong&gt;local git repo&lt;/strong&gt; before the commit is added to the database. This means if the mentioned command will have an error, the commit won't be added to the local database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LvN3T20Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zowhyz8sakx70mc1wfr3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LvN3T20Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zowhyz8sakx70mc1wfr3.gif" alt="init" width="880" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets understand some more details. For that we will add some fake AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY into our markdown file and lets try to commit it.&lt;br&gt;
Those keys are really fake, you can try 😈&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git secrets &lt;span class="nt"&gt;--register-aws&lt;/span&gt;
OK
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"This is fake aws key id AKIAIOSFODNN7EXAMPLA"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md
&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"doc(): accidentally add keys :alien:"&lt;/span&gt;
README.md:4:This is fake aws key &lt;span class="nb"&gt;id &lt;/span&gt;AKIAIOSFODNN7EXAMPLA

&lt;span class="o"&gt;[&lt;/span&gt;ERROR] Matched one or more prohibited patterns

Possible mitigations:
- Mark &lt;span class="nb"&gt;false &lt;/span&gt;positives as allowed using: git config &lt;span class="nt"&gt;--add&lt;/span&gt; secrets.allowed ...
- Mark &lt;span class="nb"&gt;false &lt;/span&gt;positives as allowed by adding regular expressions to .gitallowed at repository&lt;span class="s1"&gt;'s root directory
- List your configured patterns: git config --get-all secrets.patterns
- List your configured allowed patterns: git config --get-all secrets.allowed
- List your configured allowed patterns in .gitallowed at repository'&lt;/span&gt;s root directory
- Use &lt;span class="nt"&gt;--no-verify&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;this is a one-time &lt;span class="nb"&gt;false &lt;/span&gt;positive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see it is not possible to commit the changes to the git history because there is a AWS KEY in the change.&lt;br&gt;
In some cases you want to commit that key. Maybe because it is an example for a tutorial or anything else.&lt;br&gt;
This is quite easy to establish. Just add the key to a file called &lt;strong&gt;.gitallowed&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"AKIAIOSFODNN7EXAMPLA"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitallowed
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-S&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"doc(): now we are able to establish the commit :star:"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uTUM5E4l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mv4d5yf53mnyjy9xmd8x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uTUM5E4l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mv4d5yf53mnyjy9xmd8x.gif" alt="example-usage" width="880" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/A0A4EKB66"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>secrets</category>
      <category>security</category>
      <category>collaboration</category>
    </item>
    <item>
      <title>GIT - how and why to sign commits</title>
      <dc:creator>Andreas Augustin</dc:creator>
      <pubDate>Fri, 26 Aug 2022 22:35:00 +0000</pubDate>
      <link>https://forem.com/andreasaugustin/git-how-and-why-to-sign-commits-35dn</link>
      <guid>https://forem.com/andreasaugustin/git-how-and-why-to-sign-commits-35dn</guid>
      <description>&lt;h1&gt;
  
  
  Git - how and why sign commits
&lt;/h1&gt;

&lt;h2&gt;
  
  
  abstract
&lt;/h2&gt;

&lt;p&gt;You should always sign your git commits. Why?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why to sign commits
&lt;/h2&gt;

&lt;p&gt;The git commits are super easy referenced to a user. Anyone all around the world is able to push commits with another name. The reference is done in the commit message with the &lt;strong&gt;user.email&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can try yourself. Just create a new repository in a folder of your choice.&lt;/p&gt;

&lt;p&gt;Let's create locally a git repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;sign_commits
&lt;span class="nb"&gt;cd &lt;/span&gt;sign_commits
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3SySvEN7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/koljz83p2cghkr5pifkw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3SySvEN7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/koljz83p2cghkr5pifkw.gif" alt="init_repo" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First lets check our current global settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email
jane.doe@world.universe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and compare them with our local git repo settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are the same. Now lets change the local git repo settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email &lt;span class="s1"&gt;'john.doe@example.dev'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remark&lt;/strong&gt; You can also use &lt;code&gt;git config &amp;lt;--global&amp;gt; --edit&lt;/code&gt; to edit all configuration values in editor&lt;/p&gt;

&lt;p&gt;Lets now check the current settings and compare them to the global settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that those differ. This does not give us any value for our current context,&lt;br&gt;
but I wanted to make sure that we do not touch our global settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9hivP3Vf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l459cr4hm0j656nfn8mz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9hivP3Vf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l459cr4hm0j656nfn8mz.gif" alt="git_config" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets create a commit and check the history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# git sign commits"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"doc(): add some super nice docs"&lt;/span&gt;
git log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3DV-6Kgj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/na2nw7mfyde0tt87xkcf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3DV-6Kgj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/na2nw7mfyde0tt87xkcf.gif" alt="first_commit" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets change the user name and the mail and lets do another commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.email &lt;span class="s1"&gt;'fake.me@fake.me'&lt;/span&gt;
git config user.name &lt;span class="s1"&gt;'fake me'&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"if the account exists e.q. on github.com the commit will be assigned to that person"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"doc(): add some super nice docs"&lt;/span&gt;
git log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MWv80riT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mijbhicbsvzkrzptwsrq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MWv80riT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mijbhicbsvzkrzptwsrq.gif" alt="second_commit" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that the second commit is assigned to &lt;strong&gt;fake me&lt;/strong&gt; with mail address &lt;strong&gt;&lt;a href="mailto:fake.me@fake.me"&gt;fake.me@fake.me&lt;/a&gt;&lt;/strong&gt;.&lt;br&gt;
If you are using github.com as your git provider and push the commit and also the mail address &lt;a href="mailto:fake.me@fake.me"&gt;fake.me@fake.me&lt;/a&gt; is registered to an existing user, the commit will be assigned to that user.&lt;/p&gt;

&lt;p&gt;As you can see it is super easy to make commits in names of other persons.&lt;br&gt;
Like an example? Here is a prank of a fake Linus Torvalds stating that &lt;a href="https://github.com/slimsag/linux/tree/5895e21f3c744ed9829e3afe9691e3eb1b1932ae#linux-kernel"&gt;linux is deleted&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you can imagine there are not only pranks. This is a security issue. Imagine you are working in a team on a open source project on github. A teammate (who is a fake) is opening a pull request. You know that the original team mate is a great coder and you don't check in detail the changes and merge them into your main branch. This is obviously an attack vector. How to prevent? &lt;strong&gt;start signing your commits today&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to sign commits
&lt;/h2&gt;

&lt;p&gt;It is possible to sign git commits with &lt;strong&gt;GPG&lt;/strong&gt;.&lt;br&gt;
First lets revert our fake changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--user&lt;/span&gt;.name &lt;span class="s1"&gt;'john doe'&lt;/span&gt;
git config &lt;span class="nt"&gt;--user&lt;/span&gt;.email &lt;span class="s1"&gt;'john.doe@example.dev'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to create a gpg key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--gen-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the Dialog nd save with &lt;strong&gt;O&lt;/strong&gt;.&lt;br&gt;
Now lets grab the Key-id and add it to the git config&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gpg &lt;span class="nt"&gt;--list-key&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git config user.email&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;--global&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; user.signingkey &amp;lt;key_id&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you are able to sign your commits with the &lt;strong&gt;-S&lt;/strong&gt; flag or you add it to the git settings to make it default behaviour.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;--global&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; commit.gpgsign &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets check what has changed. We first create a signed commit and check the signature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"now the commits are signed"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"doc(): now with signed commit :star:"&lt;/span&gt;
git log &lt;span class="nt"&gt;--show-signatur&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H1Z6k07Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gdel69tgfuciqb6lgl66.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H1Z6k07Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gdel69tgfuciqb6lgl66.gif" alt="signed_commits" width="880" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should now also add the key to your git provider settings so that the git provider will verify the signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further readings
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits"&gt;github sign commits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work"&gt;git sign commits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/A0A4EKB66"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>sign</category>
      <category>security</category>
      <category>collaboration</category>
    </item>
    <item>
      <title>GIT - multi user</title>
      <dc:creator>Andreas Augustin</dc:creator>
      <pubDate>Mon, 22 Aug 2022 20:03:00 +0000</pubDate>
      <link>https://forem.com/andreasaugustin/git-multi-user-mcf</link>
      <guid>https://forem.com/andreasaugustin/git-multi-user-mcf</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;When we work on different projects, sometimes we have different git providers (e.q. GitHub, GitLab, Gitea,...).&lt;br&gt;
Also it is possible that we need to use different users for our contribution.&lt;br&gt;
This is obiously possible using git with &lt;strong&gt;https&lt;/strong&gt;.&lt;br&gt;
Because &lt;strong&gt;ssh&lt;/strong&gt; is considered more secure in context of &lt;strong&gt;git&lt;/strong&gt; you need to manage several ssh keys.&lt;/p&gt;

&lt;p&gt;It is possible to specify the key you need. For example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GIT_SSH_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ssh -i private_key_file -o IdentitiesOnly=yes'&lt;/span&gt; git clone user@host:repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see this is not super convenient.&lt;br&gt;
There is an easier way using an ssh config file.&lt;/p&gt;
&lt;h2&gt;
  
  
  Theory
&lt;/h2&gt;

&lt;p&gt;You are able to configure &lt;strong&gt;ssh&lt;/strong&gt; with a file &lt;strong&gt;~/.ssh/config&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;Remark&lt;/strong&gt; If interested you are able to find all available configration parameters &lt;a href="https://linux.die.net/man/5/ssh_config"&gt;here&lt;/a&gt;&lt;br&gt;
You are able to set the identity related to the host with the following parameters&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host &amp;lt;host&amp;gt;:&amp;lt;port&amp;gt;
  HostName &amp;lt;host&amp;gt;
  Port &amp;lt;port&amp;gt;
  IdentityFile &amp;lt;path_to_id_file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Host: add a name for the host

&lt;ul&gt;
&lt;li&gt;HostName: The domain, e.q. github.com, gitlab.com, ...&lt;/li&gt;
&lt;li&gt;IdentityFile: absolute path to the specific private ssh cert&lt;/li&gt;
&lt;li&gt;Port [OPTIONAL]: just use if you have your own git provider service running&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  setup
&lt;/h3&gt;

&lt;p&gt;Get somehow 2 users in 2 different git providers (e.q. GitHub, GitLab,...).&lt;br&gt;
Now lets create 2 different (public/private) ssh key pairs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;first_user_mail&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'~/.ssh/id_rsa_first'&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;second_user_mail&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'~/.ssh/id_rsa_second'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be able to ssh into the git provider, you need to add the private keys to your git provider settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa_first.pub
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa_second.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step is dependent on your git provider.&lt;/p&gt;

&lt;p&gt;Now we want to configure git ssh to use those files related to the git provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/.ssh/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add the following content to the file.&lt;br&gt;
The hostname is dependent to the git provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="c1"&gt;# user 1&lt;/span&gt;
&lt;span class="k"&gt;Host&lt;/span&gt; &amp;lt;first_git_provider&amp;gt;
  &lt;span class="k"&gt;HostName&lt;/span&gt; &amp;lt;hostname_1&amp;gt;
  &lt;span class="k"&gt;IdentityFile&lt;/span&gt; ~/.ssh/id_rsa_first

&lt;span class="c1"&gt;# user 2&lt;/span&gt;
&lt;span class="k"&gt;Host&lt;/span&gt; &amp;lt;second_git_provider&amp;gt;
  &lt;span class="k"&gt;HostName&lt;/span&gt; &amp;lt;hostname_2&amp;gt;
  &lt;span class="k"&gt;IdentityFile&lt;/span&gt; ~/.ssh/id_rsa_second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to &lt;strong&gt;~/.ssh/config&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  test
&lt;/h3&gt;

&lt;p&gt;Now we are set to test the settings.&lt;br&gt;
Lets first create 2 repositories. One in each git provider.&lt;/p&gt;

&lt;p&gt;Now lets clone the repositories. &lt;code&gt;cd&lt;/code&gt; in a directory of your choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;ssh_clone_url_1&amp;gt;
git clone &amp;lt;ssh_clone_url_2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to clone the repositories.&lt;br&gt;
Yay it works 🚀&lt;/p&gt;

&lt;p&gt;As you can see when that the right user is auto selected 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/A0A4EKB66"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>ssh</category>
      <category>contribution</category>
      <category>multiuser</category>
    </item>
    <item>
      <title>GIT - share secrets</title>
      <dc:creator>Andreas Augustin</dc:creator>
      <pubDate>Sun, 21 Aug 2022 20:36:00 +0000</pubDate>
      <link>https://forem.com/andreasaugustin/git-share-secrets-4c60</link>
      <guid>https://forem.com/andreasaugustin/git-share-secrets-4c60</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;In some cases you want to securely share secrets with other teammates. Furthermore you want to have a history of those secrets.&lt;br&gt;
For this purpose &lt;a href="https://github.com/AGWA/git-crypt"&gt;Git crypt&lt;/a&gt; helps you to handle secrets within your git repository.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;git-crypt enables transparent encryption and decryption of files in a git repository. Files which you choose to protect are encrypted when committed, and decrypted when checked out. git-crypt lets you freely share a repository containing a mix of public and private content.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No accidentaly push secrets in clear text&lt;/li&gt;
&lt;li&gt;Possible to Share credentials&lt;/li&gt;
&lt;li&gt;Put credentials into version control&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;First we need to install git-crypt&lt;/p&gt;

&lt;p&gt;We need &lt;code&gt;make&lt;/code&gt; for the installation.&lt;br&gt;
Please clone the &lt;a href="https://github.com/AGWA/git-crypt"&gt;repo&lt;/a&gt; and use the following commands.&lt;br&gt;
Please &lt;code&gt;cd&lt;/code&gt; in a temporary directory first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:AGWA/git-crypt.git
&lt;span class="nb"&gt;cd &lt;/span&gt;git-crypt
make
make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remarks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;for details please check &lt;a href="https://github.com/AGWA/git-crypt/blob/master/INSTALL.md"&gt;install instructions&lt;/a&gt; to install git-crpyt.&lt;/li&gt;
&lt;li&gt;For users with docker knowledge: have prepared a &lt;a href="https://hub.docker.com/repository/docker/andyaugustin/git-crypt"&gt;docker image&lt;/a&gt; where git-secret is already installed.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker run -v &amp;lt;local_git_repo&amp;gt;:/home/git-secrets/ andyaugustin/git-secrets:main git-crypt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GPG
&lt;/h3&gt;

&lt;p&gt;We need a key-pair (maybe in reality it is already created for your mail adress)&lt;br&gt;
Use the mail adress which is added to your git user&lt;/p&gt;

&lt;p&gt;First we want to check those settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email
john.doe@dummy.fake
&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name
John Doe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;keep those entries in your mind or write them down :evil_imp:&lt;/p&gt;

&lt;p&gt;Now we want to generate the gpg key.&lt;br&gt;
Type in the name and mail you just received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--gen-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  git-crypt
&lt;/h3&gt;

&lt;p&gt;We need to have a git repository available. Please create a repository with name &lt;strong&gt;git-crypt-test&lt;/strong&gt; in your favourite Git provider (e.q. GitHub, GitLab, Gitea, ...).&lt;br&gt;
Please clone the repository and &lt;code&gt;cd&lt;/code&gt; into it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;use_your_repo_url&amp;gt;/git-crypt-test
&lt;span class="nb"&gt;cd &lt;/span&gt;git-crypt-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to init &lt;strong&gt;git-crypt&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-crypt init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we want to specify files we want to monitor and handle with &lt;strong&gt;git-crypt&lt;/strong&gt;&lt;br&gt;
That is easy. Therefore we just need to add a &lt;strong&gt;.gitattributes&lt;/strong&gt; file with the files we want to encrypt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"secretfile filter=git-crypt diff=git-crypt&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;*.key filter=git-crypt diff=git-crypt&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;secretdir/** filter=git-crypt diff=git-crypt"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitattributes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The content of the &lt;strong&gt;.gitattributes&lt;/strong&gt; file should look now&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;secretfile filter=git-crypt diff=git-crypt
*.key filter=git-crypt diff=git-crypt
secretdir/** filter=git-crypt diff=git-crypt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is like a &lt;strong&gt;.gitignore&lt;/strong&gt; file and has the following content.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;handle all files with name secretfile with git-crypt&lt;/li&gt;
&lt;li&gt;handle all files with extension *.key with git-crypt&lt;/li&gt;
&lt;li&gt;handle all files within directory secretdir/ with git-crypt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we add our git user to the secrets. Therefore we need to get the id of our gpg key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--list-key&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(The id is at pub between / and the date).&lt;/p&gt;

&lt;p&gt;Copy it to any text editor.&lt;/p&gt;

&lt;p&gt;Now we add the key to the keyring of the local git repository database.&lt;br&gt;
Please replace  with the id you copied to the text editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-crypt add-gpg-user &amp;lt;USER_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we add a file for encryption.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"This file will be encrypted"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; to_encrypt.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and commit our changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"add file to encrypt :lock:"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lock the file and check it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-crypt lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;just check the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;to_encrypt.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it is encrypted. For unlocking type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-crypt unlock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the file again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;to_encrypt.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The nice thing is that it is not possible to push the unencrypted file to git repo.&lt;br&gt;
Lets test it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"add encrypted file"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the file in your favourite git provider. You can see that it is encrypted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add users to git-crypt database
&lt;/h3&gt;

&lt;p&gt;To add a user to git-crypt you need the public gpg file.&lt;br&gt;
Just tell the other users to use the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--armor&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; public-key.gpg &lt;span class="nt"&gt;--export&lt;/span&gt; &amp;lt;key_mail_address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the key file into your gpg keyring and add trust level ultimate&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--import&lt;/span&gt; public-key.gpg
&lt;span class="c"&gt;# get the id of the imported key&lt;/span&gt;
gpg &lt;span class="nt"&gt;--list-key&lt;/span&gt; &amp;lt;key_mail_address&amp;gt;
gpg &lt;span class="nt"&gt;--edit-key&lt;/span&gt; &amp;lt;key_id&amp;gt;
trust
&lt;span class="c"&gt;# We need ultimate trust, so choose 5&lt;/span&gt;
save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now you are able to add the user as before with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# the user_id is the id of the user in your public key_ring&lt;/span&gt;
git-crypt add-gpg-user &amp;lt;USER_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the other user is able to decrypt the file with git-crypt in the git repository 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/A0A4EKB66"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>secrets</category>
      <category>team</category>
      <category>collaboration</category>
    </item>
    <item>
      <title>Start a new typescript project with gts and esbuild</title>
      <dc:creator>Andreas Augustin</dc:creator>
      <pubDate>Fri, 19 Aug 2022 21:18:00 +0000</pubDate>
      <link>https://forem.com/andreasaugustin/start-a-new-typescript-project-with-gts-and-esbuild-54ka</link>
      <guid>https://forem.com/andreasaugustin/start-a-new-typescript-project-with-gts-and-esbuild-54ka</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;When starting a new typescript project you need to configure lots of things&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm project settings&lt;/li&gt;
&lt;li&gt;typescript transpiler settings&lt;/li&gt;
&lt;li&gt;folder structure&lt;/li&gt;
&lt;li&gt;style checker and formatter&lt;/li&gt;
&lt;li&gt;bundler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To minize the effort &lt;a href="https://github.com/google/gts"&gt;gts&lt;/a&gt; is a nice tool to help you setting up the project.&lt;br&gt;
Our of deployment/devliver purposes we also want to bundle the code to create nice and small artifacts.&lt;br&gt;
For those purposes we use &lt;a href="https://github.com/evanw/esbuild"&gt;esbuild&lt;/a&gt;.&lt;br&gt;
The whole example can be found &lt;a href="https://github.com/AndreasAugustin/teaching/tree/main/examples/ts_gts_esbuild"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;For starting this tutorial you need to have &lt;a href="https://nodejs.org/en/"&gt;nodejs&lt;/a&gt; and &lt;a href="https://docs.npmjs.com/about-npm"&gt;npm&lt;/a&gt; (also &lt;a href="https://www.npmjs.com/package/npx"&gt;npx&lt;/a&gt;) installed on your machine.&lt;br&gt;
Some basic knowledge about &lt;strong&gt;nodejs&lt;/strong&gt;, &lt;strong&gt;npm&lt;/strong&gt; and &lt;strong&gt;npx&lt;/strong&gt; is helpful.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create the project
&lt;/h2&gt;

&lt;p&gt;Please keep in mind that some of the outputs can vary on your system related to the used versions.&lt;/p&gt;

&lt;p&gt;So lets start some actions.&lt;br&gt;
First we want to create the npm project.&lt;br&gt;
Therefore please &lt;code&gt;cd&lt;/code&gt; into a nice directory of your choice.&lt;/p&gt;

&lt;p&gt;Now lets create the project directory and the &lt;strong&gt;npm&lt;/strong&gt; typescript project with the help of &lt;strong&gt;gts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remark&lt;/strong&gt; We add the &lt;code&gt;-y&lt;/code&gt; flag to accept the default settings. If you want to adjust those, just do not add the flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;ts_gts_esbuild
&lt;span class="nb"&gt;cd &lt;/span&gt;ts_gts_esbuild
npx gts init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Analyse
&lt;/h2&gt;

&lt;p&gt;Now lets see what we got.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 1
&lt;span class="nb"&gt;.&lt;/span&gt;
├── .eslintignore
├── .eslintrc.json
├── node_modules
├── package.json
├── package-lock.json
├── .prettierrc.js
├── src
└── tsconfig.json

2 directories, 6 files

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we do not want to add build artifacts and dependent libs to our git database we add them to &lt;strong&gt;.gitignore&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remark&lt;/strong&gt; The build/ folder is  used per default for the typescript build artefacts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;node_modules/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;echo &lt;/span&gt;build/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that we received some default settings&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm project settings&lt;/li&gt;
&lt;li&gt;typescript transpiler settings&lt;/li&gt;
&lt;li&gt;folder structure&lt;/li&gt;
&lt;li&gt;style checker and formatter&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  NPM project settings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;package.json
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
  &lt;span class="s2"&gt;"version"&lt;/span&gt;: &lt;span class="s2"&gt;"0.0.0"&lt;/span&gt;,
  &lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
  &lt;span class="s2"&gt;"main"&lt;/span&gt;: &lt;span class="s2"&gt;"build/src/index.js"&lt;/span&gt;,
  &lt;span class="s2"&gt;"types"&lt;/span&gt;: &lt;span class="s2"&gt;"build/src/index.d.ts"&lt;/span&gt;,
  &lt;span class="s2"&gt;"files"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"build/src"&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;,
  &lt;span class="s2"&gt;"license"&lt;/span&gt;: &lt;span class="s2"&gt;"Apache-2.0"&lt;/span&gt;,
  &lt;span class="s2"&gt;"keywords"&lt;/span&gt;: &lt;span class="o"&gt;[]&lt;/span&gt;,
  &lt;span class="s2"&gt;"scripts"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"test"&lt;/span&gt;: &lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;,
    &lt;span class="s2"&gt;"lint"&lt;/span&gt;: &lt;span class="s2"&gt;"gts lint"&lt;/span&gt;,
    &lt;span class="s2"&gt;"clean"&lt;/span&gt;: &lt;span class="s2"&gt;"gts clean"&lt;/span&gt;,
    &lt;span class="s2"&gt;"compile"&lt;/span&gt;: &lt;span class="s2"&gt;"tsc"&lt;/span&gt;,
    &lt;span class="s2"&gt;"fix"&lt;/span&gt;: &lt;span class="s2"&gt;"gts fix"&lt;/span&gt;,
    &lt;span class="s2"&gt;"prepare"&lt;/span&gt;: &lt;span class="s2"&gt;"npm run compile"&lt;/span&gt;,
    &lt;span class="s2"&gt;"pretest"&lt;/span&gt;: &lt;span class="s2"&gt;"npm run compile"&lt;/span&gt;,
    &lt;span class="s2"&gt;"posttest"&lt;/span&gt;: &lt;span class="s2"&gt;"npm run lint"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  &lt;span class="s2"&gt;"devDependencies"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"gts"&lt;/span&gt;: &lt;span class="s2"&gt;"^3.1.0"&lt;/span&gt;,
    &lt;span class="s2"&gt;"typescript"&lt;/span&gt;: &lt;span class="s2"&gt;"^4.0.3"&lt;/span&gt;,
    &lt;span class="s2"&gt;"@types/node"&lt;/span&gt;: &lt;span class="s2"&gt;"^14.11.2"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see some devDependencies have been installed. Also we got some preparations for delivering a npm package.&lt;br&gt;
Furthermore we got some npm scripts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Typescript transpiler settings
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will compile the typescript sources defined in &lt;strong&gt;tsconfig.json&lt;/strong&gt; file and put the built aretefacts into the outDir folder defined in &lt;strong&gt;tsconfig.json&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run clean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will cleanup the typescript build artefacts (delete the outDir directory defined in &lt;strong&gt;tsconfig.json&lt;/strong&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Style checker and formatter
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will run the style checker &lt;a href="https://github.com/eslint/eslint"&gt;eslint&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will fix some of the found lint issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  bundler
&lt;/h2&gt;

&lt;p&gt;Because we also want to bundle our project we first install esbuild as dev dependency&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; esbuild
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets test it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx esbuild src/index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is the bundled file.&lt;/p&gt;

&lt;p&gt;You can pass lots of options to the cli interface.&lt;br&gt;
&lt;em&gt;However, using the command-line interface can become unwieldy if you need to pass many options to esbuild. For more sophisticated uses you will likely want to write a build script in JavaScript using esbuild's JavaScript API.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We will do that now.&lt;br&gt;
Lets create a small nodejs binary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;bin
&lt;span class="nb"&gt;touch &lt;/span&gt;bin/esbuild.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now please copy the following content to the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env node

import esbuild from 'esbuild';

const build = esbuild.build({
  entryPoints: ["src/index.ts"],
  outdir: "dist",
  bundle: true,
  loader: {".ts": "ts"}
});

await build;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as you can see we will have the outdir &lt;strong&gt;dist&lt;/strong&gt; set. We also need to add this to our &lt;strong&gt;.gitignore&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;dist/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets test it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node bin/esbuild.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see the bundled package is built.&lt;/p&gt;

&lt;p&gt;Now we can add a new npm script. Please add a new script within the script part in &lt;strong&gt;package.json&lt;/strong&gt;. Because in addition we want to create the types we also add &lt;code&gt;npx tsc --emitDeclarationOnly --outDir dist/types&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"posttest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bundle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx tsc --emitDeclarationOnly --outDir dist/types &amp;amp;&amp;amp; node bin/esbuild.mjs"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  [option] Package
&lt;/h3&gt;

&lt;p&gt;Now we have the option to create a nice small npm package.&lt;br&gt;
Therefore we need to add a &lt;code&gt;.npmignore&lt;/code&gt; file and add some content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .npmignore
&lt;span class="nb"&gt;echo &lt;/span&gt;node_modules/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmignore
&lt;span class="nb"&gt;echo &lt;/span&gt;build/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmignore
&lt;span class="nb"&gt;echo &lt;/span&gt;bin/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmignore
&lt;span class="nb"&gt;echo &lt;/span&gt;src/ &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .npmignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also we need to adjust some paths within our &lt;strong&gt;package.json&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ts-gts-esbuild"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1.0"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/index.js"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/src/index.d.ts"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can test it now&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a tar archive in your package folder.&lt;br&gt;
You can check it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;p&gt;There are lots of pros related to this project setup. But of course there are also some cons.&lt;br&gt;
One of them is that gts is out of the box not properly working with &lt;a href="https://docs.npmjs.com/cli/v8/using-npm/workspaces"&gt;npm workspaces&lt;/a&gt; yet &lt;a href="https://github.com/google/gts/issues/718"&gt;gts issue&lt;/a&gt;.&lt;br&gt;
But you just need to do the gts init within the repos and adjust some path parameters in some files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/A0A4EKB66"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKanlt08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi" width="223" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>esbuild</category>
      <category>typescript</category>
      <category>gts</category>
      <category>collaboration</category>
    </item>
  </channel>
</rss>
