<?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: Sushil Subedi</title>
    <description>The latest articles on Forem by Sushil Subedi (@sushilsubedi).</description>
    <link>https://forem.com/sushilsubedi</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%2F326197%2F2e971ccf-98ff-40f4-a2dc-8c6ff43e47de.png</url>
      <title>Forem: Sushil Subedi</title>
      <link>https://forem.com/sushilsubedi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sushilsubedi"/>
    <language>en</language>
    <item>
      <title>How to Read EXIF Capture Time from HEIC/HEIF Photos in Ruby on Rails</title>
      <dc:creator>Sushil Subedi</dc:creator>
      <pubDate>Sat, 11 Oct 2025 04:40:49 +0000</pubDate>
      <link>https://forem.com/sushilsubedi/how-to-read-exif-capture-time-from-heicheif-photos-in-ruby-on-rails-324b</link>
      <guid>https://forem.com/sushilsubedi/how-to-read-exif-capture-time-from-heicheif-photos-in-ruby-on-rails-324b</guid>
      <description>&lt;p&gt;If you’ve ever uploaded an iPhone photo and noticed your &lt;code&gt;captured_at&lt;/code&gt; field missing, you’re not alone.&lt;br&gt;&lt;br&gt;
Modern iPhones save images as &lt;strong&gt;HEIC/HEIF&lt;/strong&gt; instead of traditional JPEGs. These formats store metadata a little differently and that’s where many Ruby EXIF libraries fall short.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through a reliable way to read photo capture dates (&lt;code&gt;DateTimeOriginal&lt;/code&gt;, &lt;code&gt;CreateDate&lt;/code&gt;, etc.) from HEIC/HEIF files inside a Rails app even if you’re using Active Storage.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;ExifTool&lt;/strong&gt; (through the &lt;code&gt;mini_exiftool&lt;/code&gt; or &lt;code&gt;exiftool&lt;/code&gt; gem), it works with HEIC/HEIF files directly.
&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;don’t need&lt;/strong&gt; to decode or convert images (&lt;code&gt;libheif&lt;/code&gt; or &lt;code&gt;libvips&lt;/code&gt;) just to read metadata.
&lt;/li&gt;
&lt;li&gt;Always convert timestamps to &lt;strong&gt;UTC&lt;/strong&gt; and check multiple EXIF date fields for reliability.
&lt;/li&gt;
&lt;li&gt;When using &lt;strong&gt;Active Storage&lt;/strong&gt;, call &lt;code&gt;blob.open&lt;/code&gt; to access a temporary file path for ExifTool.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why HEIC/HEIF can be tricky
&lt;/h2&gt;

&lt;p&gt;Here’s the issue in plain terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HEIC stores metadata inside &lt;strong&gt;QuickTime-style boxes&lt;/strong&gt;, not the standard EXIF segments used by JPEG.&lt;/li&gt;
&lt;li&gt;Most Ruby EXIF libraries (like &lt;code&gt;exifr&lt;/code&gt;) only understand &lt;strong&gt;JPEG/TIFF&lt;/strong&gt; files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ExifTool&lt;/strong&gt; is a Perl-based tool that can read just about &lt;em&gt;anything&lt;/em&gt;, including HEIC/HEIF, RAW, and Live Photo sidecars.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Install the ExifTool CLI on your machine/container:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;macOS (Homebrew): &lt;code&gt;brew install exiftool&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Debian/Ubuntu: &lt;code&gt;sudo apt-get install -y libimage-exiftool-perl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Alpine: &lt;code&gt;apk add exiftool&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then add one of these gems to your &lt;code&gt;Gemfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'exiftool'&lt;/span&gt;       &lt;span class="c1"&gt;# lightweight wrapper; also shells out to exiftool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And install them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reading EXIF data from a file
&lt;/h2&gt;

&lt;p&gt;Here’s a simple Ruby method using the &lt;code&gt;exiftool&lt;/code&gt; gem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'exiftool'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_capture_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Exiftool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_hash&lt;/span&gt; &lt;span class="c1"&gt;# symbolized keys&lt;/span&gt;
  &lt;span class="n"&gt;raw&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:date_time_original&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
         &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create_date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
         &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:media_create_date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
         &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:modify_date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utc&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;DateTime&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utc&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utc&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That’s it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ExifTool takes care of all the format quirks, so this works for HEIC, JPEG, and even Live Photos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading EXIF with Active Storage
&lt;/h2&gt;

&lt;p&gt;When your image lives in Active Storage (e.g., S3 or Disk), just open it temporarily before reading EXIF:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_capture_time_from_blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;extract_capture_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# call one of the helpers above&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This downloads the file into a Tempfile, passes its path to ExifTool, and cleans up afterward, no extra libraries required.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Normalizing &lt;code&gt;captured_at&lt;/code&gt; in your models
&lt;/h2&gt;

&lt;p&gt;When you save your capture time, normalize it to UTC and support multiple sources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;normalized_captured_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;file_path: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;client_value: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;exif_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;extract_capture_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;client_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;client_value&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;client_value&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;DateTime&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;client_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_time&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iso8601&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt;
    &lt;span class="kp"&gt;nil&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exif_time&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;client_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utc&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This way, even if the photo doesn’t have EXIF data, you can still fall back to a timestamp sent from the frontend.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;No DateTimeOriginal&lt;/code&gt;
Some devices only set &lt;code&gt;CreateDate&lt;/code&gt; or &lt;code&gt;MediaCreateDate&lt;/code&gt;. Always try fallbacks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Nil/empty type from browser&lt;/code&gt;, client uploads may send &lt;code&gt;application/octet-stream&lt;/code&gt;. Fix on the frontend by inferring a proper MIME type from the filename before direct upload; EXIF reading itself is unaffected but downstream analyzers may behave better with the right type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;It worked for JPEG but not HEIC&lt;/code&gt;, ensure you’re using ExifTool, not EXIFR, for HEIC files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://exiftool.org/" rel="noopener noreferrer"&gt;ExifTool project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nokiatech.github.io/heif/technical.html" rel="noopener noreferrer"&gt;HEIF/HEIC overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’d like to make this reusable, you can wrap the logic into a small service class, &lt;code&gt;ImageMetadataExtractor&lt;/code&gt;that returns either a UTC Time or nil.&lt;br&gt;
Once you have this in place, your app can reliably extract captured_at from any image, regardless of format. 📸&lt;/p&gt;

</description>
      <category>rails</category>
      <category>programming</category>
      <category>ruby</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🚀 Speed Up Your Images: Complete Guide to Cloudflare CDN + Amazon S3</title>
      <dc:creator>Sushil Subedi</dc:creator>
      <pubDate>Sat, 20 Sep 2025 17:50:08 +0000</pubDate>
      <link>https://forem.com/sushilsubedi/speed-up-your-images-complete-guide-to-cloudflare-cdn-amazon-s3-3g62</link>
      <guid>https://forem.com/sushilsubedi/speed-up-your-images-complete-guide-to-cloudflare-cdn-amazon-s3-3g62</guid>
      <description>&lt;p&gt;So here's the thing, I had this Rails app where images were taking forever to load. Users were bouncing, my AWS bill was getting expensive, and I was serving the same set of photos from S3 over and over again to users all around the world.&lt;/p&gt;

&lt;p&gt;After some research, I discovered that putting Cloudflare in front of my S3 bucket was basically free performance magic. Here's exactly how I did it, including the gotchas I ran into.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Actually Works
&lt;/h2&gt;

&lt;p&gt;Before I get into the how-to, let me quickly explain why this setup is so effective:&lt;/p&gt;

&lt;p&gt;When you serve images directly from S3, every single request hits your bucket. A user in Tokyo requesting an image from your US-East bucket? That's a long round trip. A user refreshing the page? Another S3 request and another charge on your AWS bill.&lt;/p&gt;

&lt;p&gt;With Cloudflare in front, images get cached at edge locations worldwide. That Tokyo user gets the image from Cloudflare's Tokyo datacenter instead of Virginia. Plus, once an image is cached, you're not paying S3 bandwidth costs for repeated requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You'll Need&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with an S3 bucket (or willingness to create one)&lt;/li&gt;
&lt;li&gt;A domain on Cloudflare (free tier works fine)&lt;/li&gt;
&lt;li&gt;About 30 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me walk you through each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up Your S3 Bucket
&lt;/h2&gt;

&lt;p&gt;First, create a new S3 bucket or use an existing one. I called mine my-app-images-2024 but you can name it whatever makes sense.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The tricky part&lt;/em&gt;: you need to turn off &lt;strong&gt;Block All Public Access.&lt;/strong&gt;&lt;br&gt;
Here's what the setting looks like:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8vvywmlqf1vk29rgrz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8vvywmlqf1vk29rgrz7.png" alt="Turn on to public access" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose your region based on where most of your users are, or just pick the one closest to you.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fotgc9jxh83e17htb5zxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fotgc9jxh83e17htb5zxc.png" alt="Bucket region" width="526" height="202"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: The Bucket Policy
&lt;/h2&gt;

&lt;p&gt;You need to add a bucket policy to actually make the images readable. This is the JSON you need to paste in (replace &lt;code&gt;my-images-bucket&lt;/code&gt; with your actual bucket name):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::my-images-bucket/*"]
    }
  ]
}

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

&lt;/div&gt;



&lt;p&gt;Go to your bucket → Permissions → Bucket Policy, paste this in, and save.&lt;br&gt;
After this, you should be able to access any image in your bucket directly:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwhtee9a86phfuxj1eps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwhtee9a86phfuxj1eps.png" alt="Bucket policy" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After this, you should be able to access any image in your bucket directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://my-images-bucket.s3.amazonaws.com/path/to/image.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Test this before moving on - upload a test image and try accessing it via the URL.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Cloudflare CNAME Setup
&lt;/h2&gt;

&lt;p&gt;Now for the good stuff. In your Cloudflare dashboard:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to DNS&lt;/li&gt;
&lt;li&gt;Add a CNAME record

&lt;ul&gt;
&lt;li&gt;Set the name to something like &lt;code&gt;images&lt;/code&gt; or &lt;code&gt;cdn&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Point it to your S3 bucket: &lt;code&gt;my-images-bucket.s3.amazonaws.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make sure the cloud is orange (proxied through Cloudflare) 🟠&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjao9jqh52wwkz2ojrm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjao9jqh52wwkz2ojrm5.png" alt="Add CNAME record" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now your images are accessible at &lt;code&gt;https://images.yourdomain.com/path/to/image.jpg&lt;/code&gt; instead of the ugly raw S3 URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Caching Rules (Where the Magic Happens)
&lt;/h2&gt;

&lt;p&gt;This is where you actually get the performance benefits. Without proper caching rules, Cloudflare might not cache your images aggressively.&lt;/p&gt;

&lt;p&gt;Go to Rules → Cache Rules and create a new Cache rule:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o59fzrov2h321dgkbz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o59fzrov2h321dgkbz8.png" alt="click on Cache Rule to create Rule" width="800" height="907"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select Cache everything Template&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyulvwai7tnkwfo3arpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyulvwai7tnkwfo3arpq.png" alt="click on cache everything" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edge Cache TTL: 1 month (images don't change often)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Browser Cache TTL: 7 days&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcij7vd7rhnjp8e27qdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcij7vd7rhnjp8e27qdy.png" alt="Add 1 months on cache, 7days on browser" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL pattern: &lt;code&gt;images.yourdomain.com/*&lt;/code&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffegp77nodqhkvnpejl08.png" alt="Add custom url where rules are applied" width="800" height="468"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I initially set this to cache for just a few hours, but realized that was stupid - images rarely change, so why not cache them for a month?&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Cloud Connector (Don't Skip This!)
&lt;/h2&gt;

&lt;p&gt;Okay, I need to be honest - I initially thought Cloud Connector was just extra fluff, but it's actually really important. It handles the technical details that make S3 work properly with Cloudflare.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's what Cloud Connector does automatically:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fixes the Host header&lt;/strong&gt; - S3 is picky about headers, and this makes sure they match what your bucket expects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes traffic correctly&lt;/strong&gt; - Makes sure requests actually reach your bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What it doesn't do (you still need cache rules):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache behavior&lt;/strong&gt; - you still need to set up those cache rules we talked about earlier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news? You get 10 free connectors even on Cloudflare's free plan, which is way more than you'll need.&lt;/p&gt;

&lt;p&gt;Go to Rule → Cloud Connector and click &lt;code&gt;Create Cloud Connector&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw62c9aoawltew1htw7d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw62c9aoawltew1htw7d6.png" alt="click on create cloud connector" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select AWS S3 since that's what we're using:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1ssfwmwp6ndbi2hbrtl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1ssfwmwp6ndbi2hbrtl.png" alt="Aws s3 bucket" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now enter your bucket information. This is where you need to be precise:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwdnirscivjma7nagsvgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwdnirscivjma7nagsvgj.png" alt="bucket name update" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; For the hostname pattern, use a wildcard like &lt;code&gt;images.yourdomain.com/*&lt;/code&gt; since you'll be serving different images from various paths:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh8cyimqn9kvy2jkwmt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh8cyimqn9kvy2jkwmt1.png" alt="wildcard domain" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This wildcard setup ensures that whether someone requests &lt;code&gt;images.yourdomain.com/user-avatars/123.jpg&lt;/code&gt; or &lt;code&gt;images.yourdomain.com/blog-posts/hero-image.png&lt;/code&gt;, the connector knows exactly which bucket to route to.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Double-check that your bucket name matches exactly what you put in the connector. I spent 20 minutes debugging why my images weren't loading, only to realize I had a typo in the bucket name. 🤦‍♂️&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Rails Helper (If You're Using Rails)
&lt;/h2&gt;

&lt;p&gt;Here's the Rails helper I wrote to make this work seamlessly with ActiveStorage:&lt;/p&gt;

&lt;p&gt;Instead, we build URLs using the blob key and point them to our Cloudflare domain.&lt;/p&gt;

&lt;p&gt;Here’s a helper module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module ApplicationHelper
  include Pagy::Frontend

  def cdn_image_url(attachment_or_blob, **opts)
    blob = attachment_or_blob.is_a?(ActiveStorage::Blob) ? attachment_or_blob : attachment_or_blob&amp;amp;.blob
    return unless blob

    base = ENV['CDN_CLOUDFLARE_URL'].presence ||
           Rails.application.routes.url_helpers.rails_blob_url(blob, only_path: false)

    url = "#{base.chomp('/')}/#{blob.key.delete_prefix('/')}"
    return url if opts.blank?

    params = opts.slice(:width, :height, :quality, :format).map { |k, v| "#{k.to_s[0]}=#{v}" }
    "#{url}?#{params.join('&amp;amp;')}"
  end
end

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then in your views:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= image_tag cdn_image_url(user.avatar, width: 300, quality: 80, format: :webp) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I set the &lt;code&gt;CDN_CLOUDFLARE_URL&lt;/code&gt; in my environment variables, so I can easily switch between development (direct S3) and production (Cloudflare CDN).&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned the Hard Way
&lt;/h2&gt;

&lt;p&gt;Cache headers matter. Initially, my images weren't being cached properly because I didn't set up the cache rules correctly.&lt;/p&gt;

&lt;p&gt;The first request is still slow. That's expected - Cloudflare has to fetch from S3 the first time. After that, it's lightning fast.&lt;/p&gt;

&lt;p&gt;ActiveStorage signed URLs don't work. If you're using Rails, you can't just use the built-in signed URLs because they have query parameters that mess with caching. That's why I built the custom helper.&lt;/p&gt;

&lt;p&gt;Test with curl. This command helped me debug caching issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -I https://images.yourdomain.com/some-image.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for &lt;code&gt;cf-cache-status: HIT&lt;/code&gt; in the response headers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worth the Effort ?
&lt;/h2&gt;

&lt;p&gt;Absolutely. This took me about 2-3 hours to set up (including debugging time), and the performance improvement was immediate and dramatic. Plus, it's basically free - Cloudflare's free tier handles this just fine for most applications.&lt;/p&gt;

&lt;p&gt;If you're serving images directly from S3, you should definitely do this. Your users will thank you, and your AWS bill will too.&lt;/p&gt;

&lt;p&gt;Got questions about the setup? Hit me up in the comments. I probably ran into the same issue when I was figuring this out!&lt;/p&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.cloudflare.com/rules/cloud-connector/" rel="noopener noreferrer"&gt;https://developers.cloudflare.com/rules/cloud-connector/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hiddify.com/manager/domain-worker-cdn-and-tunneling/How-to-use-Cloudflare-CDN/#site-or-domain-service" rel="noopener noreferrer"&gt;https://hiddify.com/manager/domain-worker-cdn-and-tunneling/How-to-use-Cloudflare-CDN/#site-or-domain-service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>webdev</category>
      <category>cdn</category>
      <category>programming</category>
    </item>
    <item>
      <title>Create Gitlab PR Template</title>
      <dc:creator>Sushil Subedi</dc:creator>
      <pubDate>Tue, 08 Feb 2022 03:51:50 +0000</pubDate>
      <link>https://forem.com/sushilsubedi/create-gitlab-pr-template-5gmp</link>
      <guid>https://forem.com/sushilsubedi/create-gitlab-pr-template-5gmp</guid>
      <description>&lt;p&gt;For any company projects or gitlab repository we need to make sure all the processes to contribute should be standardized. So, Maintaining a proper pull request standard is an important way. It will save time, energy for you and your team members. &lt;br&gt;
It also helps new team members be able to show the standard and easily onboard themselves to the team.&lt;br&gt;
The best part of creating a Pull Request (Merge Request) template in Gitlab is we can update it anytime and it can be configured in just 5 steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to create a PR template in Gitlab:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Create a folder &lt;code&gt;.gitlab/merge_request_templates&lt;/code&gt; in your project root:&lt;/strong&gt;&lt;br&gt;
Navigate to your project root and create a folder name as &lt;code&gt;.gitlab&lt;/code&gt; then we also need to add another folder inside the &lt;code&gt;.gitlab&lt;/code&gt; as &lt;code&gt;merge_request_templates&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foikwq9s2osyjui31e7lo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foikwq9s2osyjui31e7lo.png" alt="gitlab PR template" width="506" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE:  We need to create a &lt;code&gt;.md&lt;/code&gt; file and name of the file should be same name of the template you want it to appear in your gitlab repository which we will see visually in the step yet to come.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can see that I have created a file name called &lt;code&gt;default.md&lt;/code&gt; because I want to have a template name as &lt;strong&gt;default&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;2.&lt;strong&gt;Update default.md:&lt;/strong&gt;&lt;br&gt;
  Now, let's update the content inside the &lt;code&gt;default.md&lt;/code&gt; as below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ## Trello Card Link:

  - Link of a Trello card (we use [Trello] 
    (https://trello.com) for Project Management)  which was assigned for completing the feature.


 ## Tasks Done: (list of tasks completed)

  - What did you complete in this PR? Mention a list of them (we will see it in an example in upcoming steps below on how it is done in a real project)

 ## Tasks Remaining: (List of tasks remaining to be 
    implemented)

 - What is remaining to be implemented in this PR? Mention a 
   list of them 

 ## Steps to test feature:
 - How can we test the feature we implemented in this PR? You 
  could mentioned steps to test it.

 ## Screenshots:

  (if your changes has any UI updates, include screenshot of 
  the changes)

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

&lt;/div&gt;



&lt;p&gt;As I want my fellow developers to add &lt;a href="https://trello.com" rel="noopener noreferrer"&gt;trello&lt;/a&gt; card link assigned to them, add what they have completed, remaining, how can we test it and screenshots if possible.&lt;br&gt;
  This is the template format we use in &lt;a href="https://www.truemark.dev/" rel="noopener noreferrer"&gt;Truemark Technology&lt;/a&gt;  which helps the the person who is reviewing the PR know what feature they should be reviewing, link to feature description if they have any confusions and what feature is implement in this PR.&lt;/p&gt;

&lt;p&gt;3.&lt;strong&gt;Commit and push:&lt;/strong&gt;&lt;br&gt;
  Let's commit the code and push the change to our default branch which in our case is &lt;code&gt;develop&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;gt; git add .
 &amp;gt; git commit -m "create new template"
 create new template
  1 file changed, 0 insertions(+), 0 deletions(-)
  create mode 100644 .gitlab/merge_request_templates/default.md
&amp;gt; git push origin develop
  Enumerating objects: 6, done.
  Counting objects: 100% (6/6), done.
  Delta compression using up to 8 threads
  Compressing objects: 100% (3/3), done.
  Writing objects: 100% (5/5), 384 bytes | 384.00 KiB/s, done.
  Total 5 (delta 1), reused 0 (delta 0), pack-reused 0
  remote: 
  remote: To create a merge request for develop, visit:
  remote: https://gitlab.com/sushilsubedi151/template- 
          react/-/merge_requests/new? 
          merge_request%5Bsource_branch%5D=develop
remote: 
To gitlab.com:sushilsubedi151/template-react.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.&lt;strong&gt;Create a new branch to verify new template:&lt;/strong&gt;&lt;br&gt;
Let's follow below steps to verify new template:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checkout to a branch called &lt;code&gt;check-template&lt;/code&gt; with
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; git checkout -b check-template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a dummy file called &lt;code&gt;test.txt&lt;/code&gt; and add some content to it with
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "This is a test content for checking my new PR template in Gitlab" &amp;gt;&amp;gt; test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add new changes with &lt;code&gt;git add .&lt;/code&gt; and commit those changes with
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "Added test.txt to test PR template in Gitlab"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push your changes with
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin check-template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5.&lt;strong&gt;Create a merge request:&lt;/strong&gt;&lt;br&gt;
  In this step we will breakdown the process into two smaller steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose a template:&lt;/strong&gt;.
Let's create a merge request and set the target branch to &lt;code&gt;develop&lt;/code&gt; branch. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: Make sure we have set default branch as develop.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To set the default branch from &lt;strong&gt;master&lt;/strong&gt; to &lt;strong&gt;develop&lt;/strong&gt;, we need to follow below steps:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F57oazp2ceks7y3ojs0o6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F57oazp2ceks7y3ojs0o6.png" alt="select repository from settings" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Let's select &lt;strong&gt;Repository&lt;/strong&gt; from &lt;strong&gt;Settings&lt;/strong&gt; as shown above.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmi9jed8esxv6z3sl7p9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmi9jed8esxv6z3sl7p9i.png" alt="select the develop as default branch" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, Let's select &lt;strong&gt;develop&lt;/strong&gt; from the list of branches and click on &lt;strong&gt;Save Changes&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to create a merge request by selecting &lt;code&gt;Merge Requests&lt;/code&gt; and click on &lt;code&gt;New Merge Request&lt;/code&gt;.After, that we need select from the template list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft958mswtvfem1dc648xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft958mswtvfem1dc648xf.png" alt="pr template list" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see, &lt;strong&gt;default&lt;/strong&gt; as our template name.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Edit the template:&lt;/strong&gt;
In this step, we will be update the selected template.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Food2mac56mspent32ib8.png" alt="update the pr template" width="800" height="797"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my case, I have just updated the content of test.so, I have remove &lt;strong&gt;Steps to test feature&lt;/strong&gt;, &lt;strong&gt;Screenshots&lt;/strong&gt; and updated Task completed and remaining task. After this click over &lt;code&gt;Create Merge Request&lt;/code&gt;. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfacxhu855v1cnu2iiwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfacxhu855v1cnu2iiwm.png" alt="create a PR" width="800" height="643"&gt;&lt;/a&gt;&lt;br&gt;
✅ we have successfully create a merge request using our template.🎉🎉🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
 I hope this article help to create a standard format for your team. Thank you so much for reading my blog! I really appreciate it!👏&lt;/p&gt;

</description>
      <category>git</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to rename files so that git can detect it.</title>
      <dc:creator>Sushil Subedi</dc:creator>
      <pubDate>Sat, 29 Jan 2022 16:32:00 +0000</pubDate>
      <link>https://forem.com/sushilsubedi/how-to-rename-files-so-that-git-can-detect-it-2213</link>
      <guid>https://forem.com/sushilsubedi/how-to-rename-files-so-that-git-can-detect-it-2213</guid>
      <description>&lt;p&gt;Renaming files on &lt;strong&gt;git&lt;/strong&gt; can be really painful to deal with. Git is case insensitive, so we can’t rename the file and hope for them to be updated in the &lt;strong&gt;remote repository&lt;/strong&gt;. It can also create all sorts of  &lt;strong&gt;problems&lt;/strong&gt; for yourself and your team.&lt;br&gt;
Today, I will point down a step by step process to solve this particular problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;br&gt;
Let’s discuss what happen when you manually tried to rename &lt;code&gt;Containers&lt;/code&gt; to &lt;code&gt;container&lt;/code&gt;. Also, keep a close eye on the git lens change in sidebar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyri53zdomxr60aq8km9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyri53zdomxr60aq8km9.png" alt="Before manually renaming" width="306" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqiz8fzp4iivm3wji4o4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqiz8fzp4iivm3wji4o4a.png" alt="After manually renaming" width="301" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We tried to manually change the files name from &lt;code&gt;uppercase&lt;/code&gt; to &lt;code&gt;lowercase&lt;/code&gt; which git  wasn’t able to detect. Let's see if our remote repository also has the same naming conversion problem after we push the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wtj8d8a26mmphuyqws3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6wtj8d8a26mmphuyqws3.png" alt="remote repository after renaming manually" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It seems the &lt;code&gt;git&lt;/code&gt; wasn't able to detect the case-sensitive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s see how we can solve the problem and make &lt;code&gt;git&lt;/code&gt; detect our file changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
There could be multiple way we could solve case-sensitive problem and we would use two different ways to solve the problem. Let's move on to our first solution.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using git-mv command:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git mv &amp;lt;your_file_name&amp;gt;&amp;lt;temporary_file_name&amp;gt;
git mv &amp;lt;temporary_file_name&amp;gt;&amp;lt;new_file_name&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Let's make sure we have navigated to file location before using above command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2mdy20gf2o6wrr7e7gk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2mdy20gf2o6wrr7e7gk.png" alt="using git-mv command" width="680" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The above command will delete the file or folder and add a new one with the same content. You can achieve the same facility by deleting the file and adding a new one with the same content. &lt;code&gt;Git&lt;/code&gt; facilitates the process as you don't need to manually delete a file. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;It will work on both folder and files cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s use the same command on other remaining files as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yj0i8x155b3oeftlrk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yj0i8x155b3oeftlrk0.png" alt="renaming Logo.png to logo.png file" width="699" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Logo.svg to logo.svg&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytjht6l96cwdzrcpmawo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytjht6l96cwdzrcpmawo.png" alt="renaming App.js file to app.js" width="708" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;App.js to app.js&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After renaming the above files, we should commit and push the changes to the remote repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4pdrbgq8mfkqj9dyucy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4pdrbgq8mfkqj9dyucy.png" alt="remote repository after git mv command" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We finally made the changes on the remote repository as well. And it worked!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2.&lt;strong&gt;Second Method:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This method will be a little different than the previous one. We are going to &lt;strong&gt;manually&lt;/strong&gt; change the name but we have to add an extra symbol or letter to it. Don’t worry, I will explain it more so that you can understand how it works. &lt;/p&gt;

&lt;p&gt;Let’s break down the process into two different steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;. In the first step, we are going to rename &lt;code&gt;Containers&lt;/code&gt; to &lt;code&gt;containers-1&lt;/code&gt;. I have renamed it &lt;code&gt;containers-1&lt;/code&gt;, so that I will have zero confusion in the next step. Although you can rename with whatever you want, I will suggest a name with more readability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y8tz7xkceuneoo21p51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y8tz7xkceuneoo21p51.png" alt="renaming App.js to app.js" width="330" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As we could see above, &lt;code&gt;git&lt;/code&gt; will detect the changes as a given folder &lt;code&gt;Containers&lt;/code&gt; was deleted and another new folder &lt;code&gt;containers-1&lt;/code&gt; is added but reality is we only changed the name of the folder.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s make the changes to other files as well &lt;code&gt;App.js&lt;/code&gt; to &lt;code&gt;app-1.js&lt;/code&gt; and &lt;code&gt;Logo.svg&lt;/code&gt; to &lt;code&gt;logo-1.svg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ia9i93s8q49o9oat5hh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ia9i93s8q49o9oat5hh.png" alt="renaming all file manually" width="301" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before moving to the next step, we should commit our changes so that our changes are save in our local device.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; git add .
 git commit -m “temporary name change”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9ql332qenqhtrob32d2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9ql332qenqhtrob32d2.png" alt="committing the changes" width="735" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B&lt;/strong&gt;. In this step, we will follow the same exact process but this time we rename the file  to the exact name which we want. In our case, it will be  &lt;code&gt;containers-1&lt;/code&gt; to  &lt;code&gt;containers&lt;/code&gt;. Let’s make the changes with other files as well &lt;code&gt;app-1.js&lt;/code&gt; to &lt;code&gt;app.js&lt;/code&gt;, &lt;code&gt;logo-1.svg&lt;/code&gt; to &lt;code&gt;logo.svg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktmiieczz91bja2zsu17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktmiieczz91bja2zsu17.png" alt="rename the remaining files" width="307" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After you change the name, we have to  commit the changes and push it to remote repository.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m “Manually changing name”
git push origin master.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5kj9xd1dn85euoxcvew8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5kj9xd1dn85euoxcvew8.png" alt="committing manually changed file name" width="751" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4vpdgyah7oh5eu3knqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4vpdgyah7oh5eu3knqm.png" alt="Containers to container" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We successfully changed our files and folder names in our local system as well as remotely. It worked!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Containers to containers&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffolayhnmlk0ej73kq70p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffolayhnmlk0ej73kq70p.png" alt="App to app.js" width="800" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;App.js to app.js&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh25ai6i7dpiit5zdxnxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh25ai6i7dpiit5zdxnxj.png" alt="Logo.png to logo.svg" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Logo.svg to logo.svg&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;To summarize&lt;/strong&gt;, both methods are effective and work with all scenarios.&lt;br&gt;
You can use any method as you prefer. And if you have a different approach which can solve this problem much easier than please do feel free to share it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>git</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
