<?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>DEV Community: Alain Mauri</title>
    <description>The latest articles on DEV Community by Alain Mauri (@wildeng).</description>
    <link>https://dev.to/wildeng</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%2F182743%2F9415616b-1f21-4a4f-ae91-68bc577a0d4a.jpeg</url>
      <title>DEV Community: Alain Mauri</title>
      <link>https://dev.to/wildeng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wildeng"/>
    <language>en</language>
    <item>
      <title>My GIT cookbook  </title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Thu, 13 Aug 2020 13:52:52 +0000</pubDate>
      <link>https://dev.to/wildeng/my-git-cookbook-2ff</link>
      <guid>https://dev.to/wildeng/my-git-cookbook-2ff</guid>
      <description>&lt;h1&gt;
  
  
  A collection of commands I often use
&lt;/h1&gt;

&lt;p&gt;This is a work in progress collection of common and less common GIT command I found useful in my day to day job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# compact log and graph
git log --oneline --graph

# log actual changes in a file
git log -p &amp;lt;filename&amp;gt;

# log changes not yet merged to the parent branch
git log --no-merges &amp;lt;parent-branch&amp;gt;..
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Branches management
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# if you want to rename a branch
git branch -m &amp;lt;oldname&amp;gt; &amp;lt;newname&amp;gt;
# if you want to rename the current branch
git branch -m &amp;lt;newname&amp;gt;
# push and delete the old branch
git push &amp;lt;remote&amp;gt; --delete &amp;lt;old_name&amp;gt;
# or
git push &amp;lt;remote&amp;gt; :&amp;lt;oldname&amp;gt;
# push the new branch and reset the upstream branch
git push &amp;lt;remote&amp;gt; -u &amp;lt;newname&amp;gt;

# Check available local and remote branches
git branch -v -r

# Change the URL of a remote
git remote --set-url &amp;lt;remote URL&amp;gt;

# Remove old remote tracking branches
git remote prune origin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Committing changes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Multi-Line message with commit
&lt;/h4&gt;

&lt;p&gt;To write a multi-line commit without opening the editor, use the -m option using single or double quotes, without closing them. Once you finish typing, close the quotes and you will have your nice message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m 'Feature: Add ignore files to rubocop
quote&amp;gt;
quote&amp;gt;
* Added routes.rb to rubocop ignore file'
[branchname 387aa73] Feature: Add ignore files to rubocop
1 file changed, 1 insertion(+)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Commit message using the editor and a template
&lt;/h4&gt;

&lt;p&gt;If you want to use an editor for the commit and prefer to have a template that will be consistent all across your commits you can drop a &lt;code&gt;.gitmessage&lt;/code&gt; file in your home folder with something similar in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Refactoring/Bugfix/Feature: Title
* Description
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An then tell GIT that you want to use that file, passing its absolute path, otherwise it will be interpreted as relative:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config commit.template /absolute/path/to/.gitmessage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  miscellaneous
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# fix the last made commit
git commit --amend
# edit the previous n commits
git rebase -i HEAD~n
# undo the last n commits
git reset HEAD~n
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  General
&lt;/h3&gt;

&lt;h4&gt;
  
  
  List Files with conflicts when merging
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git diff --name-only --diff-filter=U
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Stop tracking files added to .gitignore
&lt;/h4&gt;

&lt;p&gt;Sometimes happens that after adding a file or a folder to &lt;code&gt;.gitignore&lt;/code&gt; you're still seeing it in a &lt;code&gt;git status&lt;/code&gt;.&lt;br&gt;
What you have to do is removing the files or the folder from the cache using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git rm --cached &amp;lt;filename&amp;gt;
# or
git rm --cached -r /path/to/folder/**/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This list will probably increase as soon as I will learn something new, so...&lt;/p&gt;

&lt;p&gt;Stay Tuned!&lt;/p&gt;

</description>
      <category>git</category>
      <category>commandline</category>
      <category>wip</category>
      <category>cookbook</category>
    </item>
    <item>
      <title>Thoughts on Merge vs Rebase</title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Wed, 08 Jul 2020 07:34:54 +0000</pubDate>
      <link>https://dev.to/wildeng/thoughts-on-merge-vs-rebase-43fc</link>
      <guid>https://dev.to/wildeng/thoughts-on-merge-vs-rebase-43fc</guid>
      <description>&lt;p&gt;Both  merge and rebase offer the same service which is incorporating commits from one branch into another, but how is this done?&lt;/p&gt;

&lt;h2&gt;
  
  
  Merge
&lt;/h2&gt;

&lt;p&gt;Given the two following branches&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;      A---B---C Release
     /
D---E---F---G Development
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And given that the current branch is Development, when you perform a merge:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git merge Release&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The merge will replay all the changes that have been made on Release since it diverged from Development up to commit C, on top of Development, recording the result in a new commit along with the names of the two parent commits and a log message from the user describing the changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;      A---B---C Release
     /         &lt;span class="se"&gt;\&lt;/span&gt;
D---E---F---G---H Development
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An example of a merge commit from some code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;commit ca617c46f71507d1bdf44d452e1a7f0a6740c344
Merge: ea47a12b3 e16cbd937
Author: Foo Bar &amp;lt;foo.bar@funnyplace.fu&amp;gt;
Date:   Wed Mar 18 12:42:03 2020 +0000

    Merge pull request &lt;span class="c"&gt;#836 in Baz/funny-services from bar/FAB-579 to development&lt;/span&gt;

    &lt;span class="k"&gt;*&lt;/span&gt; commit &lt;span class="s1"&gt;'e16cbd937937bd368c28bd7677f211997231a4f1'&lt;/span&gt;:
      FAB-479 removed breaking dependency
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Whats is the downside of merge? If used too liberally, merge commits could clutter your git log, making difficult to understand the flow of the project changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--decorate&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;

|/ / /  
&lt;span class="k"&gt;*&lt;/span&gt; | |   d61503b9e &lt;span class="o"&gt;(&lt;/span&gt;tag: 1.0.14&lt;span class="o"&gt;)&lt;/span&gt; Merge pull request &lt;span class="c"&gt;#753 in FUN/funny-services from foobaz/TEAM-487-a to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; | | ea8052a6c &lt;span class="o"&gt;(&lt;/span&gt;origin/foobaz/TEAM-487-a&lt;span class="o"&gt;)&lt;/span&gt; TEAM-487 add mongo ssl/auth &lt;span class="k"&gt;for &lt;/span&gt;progressive
&lt;span class="k"&gt;*&lt;/span&gt; | | |   534cc7abf Merge pull request &lt;span class="c"&gt;#745 in FUN/funny-services from foobaz/TEAM-487-a to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ \ &lt;/span&gt; 
| |/ / /  
| &lt;span class="k"&gt;*&lt;/span&gt; | | 2bc74b0c7 TEAM-487: Customer - some &lt;span class="nb"&gt;nice &lt;/span&gt;stuff
|/ / /  
&lt;span class="k"&gt;*&lt;/span&gt; | |   721565549 Merge pull request &lt;span class="c"&gt;#752 in FUN/funny-services from foo/HEART-93-mongoclient-auth to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; | | c1ba829fd &lt;span class="o"&gt;(&lt;/span&gt;origin/foo/HEART-93-mongoclient-auth&lt;span class="o"&gt;)&lt;/span&gt; HEART-93 lib release versions.
| &lt;span class="k"&gt;*&lt;/span&gt; | |   9f3d3a443 Merge branch &lt;span class="s1"&gt;'development'&lt;/span&gt; into foo/HEART-93-mongoclient-auth
| |&lt;span class="se"&gt;\ \ \ &lt;/span&gt; 
| |/ / /  
|/| | |   
&lt;span class="k"&gt;*&lt;/span&gt; | | |   82e3b898d Merge pull request &lt;span class="c"&gt;#751 in FUN/funny-services from baz/TEAM-A-638 to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ \ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; | | | f920814a5 &lt;span class="o"&gt;(&lt;/span&gt;origin/baz/TEAM-A-638&lt;span class="o"&gt;)&lt;/span&gt; TEAM-A-638 Fixed variable name
| &lt;span class="k"&gt;*&lt;/span&gt; | | | 688a166d8 TEAM-A-638 Added missing content
&lt;span class="k"&gt;*&lt;/span&gt; | | | |   271e8d3c8 Merge pull request &lt;span class="c"&gt;#744 in FUN/funny-services from baz/TEAM-A-638 to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ \ \ &lt;/span&gt; 
| |/ / / /  
| &lt;span class="k"&gt;*&lt;/span&gt; | | | 1ebb5100a TEAM-A-638 removed useless comments
| &lt;span class="k"&gt;*&lt;/span&gt; | | | d03467db6 TEAM-A-638 refactored packages and classes
| &lt;span class="k"&gt;*&lt;/span&gt; | | | 08064700b TEAM-A-638 renamed controller file name
| &lt;span class="k"&gt;*&lt;/span&gt; | | | 59c93e015 TEAM-A-638 add deactivation control and model + tests
&lt;span class="k"&gt;*&lt;/span&gt; | | | |   8c3b6b33a Merge pull request &lt;span class="c"&gt;#747 in FUN/funny-services from foobaz/TEAM-528 to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ \ \ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; | | | | f61fa3a90 &lt;span class="o"&gt;(&lt;/span&gt;origin/foobaz/TEAM-528&lt;span class="o"&gt;)&lt;/span&gt; TEAM-528: upload tool to &lt;span class="nb"&gt;source &lt;/span&gt;control.
| |/ / / /  
| | &lt;span class="k"&gt;*&lt;/span&gt; | | 9a2cc0515 HEART-93 changes to support catch-up.
| | &lt;span class="k"&gt;*&lt;/span&gt; | |   636f5db20 Merge branch &lt;span class="s1"&gt;'development'&lt;/span&gt; into foo/HEART-93-mongoclient-auth
| | |&lt;span class="se"&gt;\ \ \ &lt;/span&gt; 
| |_|/ / /  
|/| | | |   
&lt;span class="k"&gt;*&lt;/span&gt; | | | |   946f4e8d4 Merge pull request &lt;span class="c"&gt;#749 in FUN/funny-services from bar/FAB-420-resolve-client-ids to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ \ \ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; | | | | 97531eb5a &lt;span class="o"&gt;(&lt;/span&gt;origin/bar/FAB-420-resolve-client-ids&lt;span class="o"&gt;)&lt;/span&gt; FAB-420 Fixed missing error message
| &lt;span class="k"&gt;*&lt;/span&gt; | | | | d54f7c7da FAB-420 Added client &lt;span class="nb"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; | | | | |   fbb71d8e1 Merge pull request &lt;span class="c"&gt;#748 in FUN/funny-services from foobaz/TEAM-419-add-back-in to development&lt;/span&gt;
|&lt;span class="se"&gt;\ \ \ \ \ \ &lt;/span&gt; 
| |/ / / / /  
|/| | | | |   
| &lt;span class="k"&gt;*&lt;/span&gt; | | | | caad3ef9a &lt;span class="o"&gt;(&lt;/span&gt;origin/foobaz/TEAM-419-add-back-in&lt;span class="o"&gt;)&lt;/span&gt; TEAM-419: Customer - re-adding endpoint &lt;span class="k"&gt;for &lt;/span&gt;Customer
|/ / / / /  
| | &lt;span class="k"&gt;*&lt;/span&gt; | |   91588ab17 Merge branch &lt;span class="s1"&gt;'development'&lt;/span&gt; into foo/HEART-93-mongoclient-auth
| | |&lt;span class="se"&gt;\ \ \ &lt;/span&gt; 
| |_|/ / /  
|/| | | |   
&lt;span class="k"&gt;*&lt;/span&gt; | | | |   70aa26022 Merge pull request &lt;span class="c"&gt;#733 in FUN/funny-services from foobaz/TEAM-503 to development&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Rebase
&lt;/h2&gt;

&lt;p&gt;Given the same branches as before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;      A---B---C Release
     /
D---E---F---G Development
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;suppose that the current branch is Release and that you want to update it, to include all the latest changes that have been merged into Development.  This the case where rebase is really helpful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase Development

D---E---F---G---A&lt;span class="s1"&gt;'---B'&lt;/span&gt;&lt;span class="nt"&gt;---C&lt;/span&gt;&lt;span class="s1"&gt;' Release
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To perform this operation Git goes back in the history until it finds the common ancestor ( commit E ),  gets all the diffs introduced by your changes and saves them in temporary files. It then resets the current branch ( Release) to the same commit as the branch you're rebasing onto ( Development commit G) and then finally applies all your changes in turn. You then end up with a clean and linear history.&lt;/p&gt;

&lt;p&gt;Keep in mind that, although the applied changes are exactly the same, from Git perspective these are new commits with a new SHA, meaning that you're rewriting the history of your branch.&lt;/p&gt;

&lt;p&gt;From Git manual, the main difference between merge and rebase:&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Rebasing replays changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;When to use merge and when to use rebase&lt;/p&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use merge if you want a set of commits clearly grouped in history&lt;/li&gt;
&lt;li&gt;User rebase if you want a linear history and if you're contributing to a bigger projects that you don't control. In this case rebasing your branch means that you solve all the conflicts locally and the project's maintainer does not have to do any integration work.&lt;/li&gt;
&lt;li&gt;Do not use rebase on a shared branch - Don't rebase &lt;strong&gt;Development/Main&lt;/strong&gt; onto a working branch. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>git</category>
      <category>newbie</category>
      <category>merge</category>
      <category>rebase</category>
    </item>
    <item>
      <title>Another GIT Introduction part 2</title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Wed, 08 Jul 2020 07:03:48 +0000</pubDate>
      <link>https://dev.to/wildeng/another-git-introduction-part-2-470</link>
      <guid>https://dev.to/wildeng/another-git-introduction-part-2-470</guid>
      <description>&lt;p&gt;&lt;i&gt;I'm posting here a series of introductory articles I wrote on another platform, hoping you will enjoy them&lt;i&gt; &lt;/i&gt;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;In my previous article, I wrote about the differences between GIT and other versioning systems, some basic terminology, states and working areas, what is the heart of a GIT system and the object it stores.&lt;/p&gt;

&lt;p&gt;Starting from the last point, I want to recall what are the objects that GIT stores: &lt;i&gt;Blobs, Trees, Commits and Tags.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;But where and how are these objects stored?&lt;/p&gt;

&lt;p&gt;At the core of GIT there is a simple key-value data store, that gives you the capability of storing whatever kind of content you want. The system will give you back a key that can be used to retrieve the data at any time.&lt;/p&gt;

&lt;p&gt;When you initialise a new repository, GIT creates a &lt;strong&gt;.git&lt;/strong&gt; folder, with some others sub-folders: &lt;strong&gt;objects, objects/info, objects/pack&lt;/strong&gt; as you can see from the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git init plain_git
Initialized empty Git repository &lt;span class="k"&gt;in&lt;/span&gt; /tmp/plain_git/.git/
&lt;span class="nb"&gt;cd &lt;/span&gt;plain_git
find .git/objects
.git/objects
.git/objects/pack
.git/objects/info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Obviously, at this point there aren't any object in the repository and you need to add one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;status.txt
&lt;span class="c"&gt;# Now edit and save the file&lt;/span&gt;
&lt;span class="c"&gt;# check the status of the repository&lt;/span&gt;

git status
On branch master

No commits yet

Untracked files:
  &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add &amp;lt;file&amp;gt;..."&lt;/span&gt; to include &lt;span class="k"&gt;in &lt;/span&gt;what will be committed&lt;span class="o"&gt;)&lt;/span&gt;

    status.txt

nothing added to commit but untracked files present &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add"&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# add the file to the staging area &lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# then save it to your repository&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"first commit"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; 51dcfd9] first commit
 1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 status.txt

&lt;span class="c"&gt;# Now check the objects created&lt;/span&gt;

find .git/objects
.git/objects
.git/objects/51
.git/objects/51/e1acfa6ecdb46d6c9d4ad13e82b5cab90d5f3f
.git/objects/51/dcfd9bba09650f50ccad8dde3ad5fe8ba68ad2
.git/objects/pack
.git/objects/info
.git/objects/53
.git/objects/53/8d4c75373bb8ebb9af381c4e8287b6f0819533
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What happens when you create a file? When you run the git status command, GIT checks if the file was in the previous snapshot of your repository and, if not, marks it as untracked.&lt;/p&gt;

&lt;p&gt;To start tracking it, you need to add it to the staging area using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &amp;lt;file-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point the file is staged and ready to be committed using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"first commit"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After committing, using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;find .git/objects &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;we can take a look at what kind of files GIT creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;find .git/objects &lt;span class="nt"&gt;-type&lt;/span&gt; f
.git/objects/51/e1acfa6ecdb46d6c9d4ad13e82b5cab90d5f3f
.git/objects/51/dcfd9bba09650f50ccad8dde3ad5fe8ba68ad2
.git/objects/53/8d4c75373bb8ebb9af381c4e8287b6f0819533
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, after a commit GIT creates three files under the '51' and '53' sub-folders, but where these names come from?&lt;br&gt;
When you commit a file, GIT calculates a 40-characters checksum hash for your file content plus a header in the following way&lt;br&gt;
First it calculates the header&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;type-of-content&amp;gt; + &amp;lt;space&amp;gt; + &amp;lt;content size&amp;gt; +&amp;lt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;null char&lt;span class="o"&gt;)&lt;/span&gt;
eg: blob 7&lt;span class="se"&gt;\0&lt;/span&gt;00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It then concatenates the header to the content&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;header&amp;gt; + &amp;lt;content&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and calculates the SHA-1 checksum of this new content.&lt;/p&gt;

&lt;p&gt;The '51' and '53' sub-folder names are directly coming from the first two digits of the checksum, while the filenames are the remaining 38 characters.&lt;br&gt;
Now, let's take a look at the files in detail using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Tree object&lt;/span&gt;
git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; 51e1acfa6ecdb46d6c9d4ad13e82b5cab90d5f3f
100644 blob 538d4c75373bb8ebb9af381c4e8287b6f0819533    status.txt

&lt;span class="c"&gt;# Commit object: Author info, Committer info and commit message&lt;/span&gt;
git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; 51dcfd9bba09650f50ccad8dde3ad5fe8ba68ad2
tree 51e1acfa6ecdb46d6c9d4ad13e82b5cab90d5f3f
author wildeng &amp;lt;wildeng@myemail.com&amp;gt; 1563483367 +0100
committer wildeng &amp;lt;wildeng@myemail.com&amp;gt; 1563483367 +0100

first commit

&lt;span class="c"&gt;# Content of the file&lt;/span&gt;
git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; 538d4c75373bb8ebb9af381c4e8287b6f0819533
This is my first commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you could see, I used the command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git cat-file -p &amp;lt;SHA-1&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;which is a sort of Swiss army knife for GIT objects. It helps you inspecting any kind of GIT object and the -p option prints in a nice form its content.&lt;/p&gt;

&lt;p&gt;If, for example, you apply it to a commit it will first uncompress the file and then it will nicely display it on STDOUT.&lt;/p&gt;

&lt;p&gt;As a reference, here is the output of the -h option ( help )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git cat-file &lt;span class="nt"&gt;-h&lt;/span&gt;
usage: git cat-file &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; - allow-unknown-type] | &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; - allow-unknown-type] | &lt;span class="nt"&gt;-e&lt;/span&gt; | &lt;span class="nt"&gt;-p&lt;/span&gt; | &amp;lt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; | - textconv | - filters&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; - &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;path&amp;gt;] &amp;lt;object&amp;gt;
 or: git cat-file &lt;span class="o"&gt;(&lt;/span&gt; - batch | - batch-check&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; - follow-symlinks] &lt;span class="o"&gt;[&lt;/span&gt; - textconv | - filters]
&amp;lt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; can be one of: blob, tree, commit, tag
 &lt;span class="nt"&gt;-t&lt;/span&gt; show object &lt;span class="nb"&gt;type&lt;/span&gt;
 &lt;span class="nt"&gt;-s&lt;/span&gt; show object size
 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;with zero when there&lt;span class="s1"&gt;'s no error
 -p pretty-print object'&lt;/span&gt;s content
 - textconv &lt;span class="k"&gt;for &lt;/span&gt;blob objects, run textconv on object&lt;span class="s1"&gt;'s content
 - filters for blob objects, run filters on object'&lt;/span&gt;s content
 - path &amp;lt;blob&amp;gt; use a specific path &lt;span class="k"&gt;for&lt;/span&gt; - textconv/ - filters
 - allow-unknown-type allow &lt;span class="nt"&gt;-s&lt;/span&gt; and &lt;span class="nt"&gt;-t&lt;/span&gt; to work with broken/corrupt objects
 - buffer buffer - batch output
 - batch[&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;format&amp;gt;] show info and content of objects fed from the standard input
 - batch-check[&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;format&amp;gt;]
 show info about objects fed from the standard input
 - follow-symlinks follow &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="nt"&gt;-tree&lt;/span&gt; symlinks &lt;span class="o"&gt;(&lt;/span&gt;used with - batch or - batch-check&lt;span class="o"&gt;)&lt;/span&gt;
 - batch-all-objects show all objects with - batch or - batch-check
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As a final step let's add a tag to our repository and see what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Adding a tag to our commit&lt;/span&gt;
git tag &lt;span class="nt"&gt;-a&lt;/span&gt; v0.1 &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"a nice commit"&lt;/span&gt;

&lt;span class="c"&gt;# looking for the created files we see that one more file&lt;/span&gt;
&lt;span class="c"&gt;# has been created&lt;/span&gt;
find .git/objects &lt;span class="nt"&gt;-type&lt;/span&gt; f
.git/objects/51/e1acfa6ecdb46d6c9d4ad13e82b5cab90d5f3f
.git/objects/51/dcfd9bba09650f50ccad8dde3ad5fe8ba68ad2
.git/objects/53/8d4c75373bb8ebb9af381c4e8287b6f0819533

&lt;span class="c"&gt;# new folder and new file created&lt;/span&gt;
.git/objects/11/85637c960727f803e5229393839629479c7b8d

&lt;span class="c"&gt;# content of the TAG object&lt;/span&gt;
git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; 1185637c960727f803e5229393839629479c7b8d
object 51dcfd9bba09650f50ccad8dde3ad5fe8ba68ad2
&lt;span class="nb"&gt;type &lt;/span&gt;commit
tag v0.1
tagger wildeng &amp;lt;wildeng@myemail.com&amp;gt; 1563610234 +0100

a &lt;span class="nb"&gt;nice &lt;/span&gt;commit

a &lt;span class="nb"&gt;nice &lt;/span&gt;tag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When you add a tag, git creates a new object with its own SHA-1 checksum and creates a sub-folder to store it.&lt;br&gt;
In this object, GIT saves the information about the object type that has been tagged - a commit - , the annotation used - v0.1 - , the author of the tag and the human readable message added to the tag.&lt;br&gt;
Now you should have an understanding of what GIT is doing when you commit a file, what are the objects involved and how GIT stores them.&lt;br&gt;
In the next episode I will talk about what happens in a basic GIT workflow, how you can take a look at the history of the repository and how you can change it.&lt;br&gt;
Enjoy!&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-Objects"&gt;GIT - GIT Objects&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learning.oreilly.com/library/view/git-pocket-guide/9781449327507/"&gt;GIT Pocket Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>introduction</category>
      <category>newbie</category>
    </item>
    <item>
      <title>Apple animated logo</title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Sun, 24 May 2020 20:25:02 +0000</pubDate>
      <link>https://dev.to/wildeng/apple-animated-logo-2o7g</link>
      <guid>https://dev.to/wildeng/apple-animated-logo-2o7g</guid>
      <description>&lt;p&gt;It's been a rainy day, so I decided to have some fun while listening to some music :)&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/wildeng/embed/abvMgxJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
    </item>
    <item>
      <title>Another GIT Introduction - part 1</title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Thu, 16 Apr 2020 07:29:46 +0000</pubDate>
      <link>https://dev.to/wildeng/another-git-introduction-part-1-598b</link>
      <guid>https://dev.to/wildeng/another-git-introduction-part-1-598b</guid>
      <description>&lt;p&gt;&lt;i&gt;I'm posting here a series of introductory articles I wrote on another platform, hoping you will enjoy them&lt;i&gt; &lt;/i&gt;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;The main difference from GIT and other control versioning systems &lt;em&gt;-Subversion for example -&lt;/em&gt; is the way it thinks about its data. What usually happens with other systems is that they store data as a set of files and the changes made on each file over time, while GIT thinks about its data as a series of snapshots of a mini filesystem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k6D7OfGI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.github.com/wildeng/articles-images/master/svn-manages-changes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6D7OfGI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.github.com/wildeng/articles-images/master/svn-manages-changes.png" alt="svn manages changes"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How a Subversion style system manages changes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This means that every time you commit, it takes a picture of your project at that moment and saves a reference to it and. As a matter of efficiency, if a file has not been changed, it saves only a link to the previous file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ARvbfxYg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.github.com/wildeng/articles-images/master/git-manages-changes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ARvbfxYg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.github.com/wildeng/articles-images/master/git-manages-changes.png" alt="svn manages changes"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How GIT manages changes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Another important fact about GIT is that almost every operation is local and generally, you do not need to go online because the entire history of your project is stored locally. Because of this, most of the operations seems instantaneous.&lt;/p&gt;

&lt;h4&gt;
  
  
  GIT states and terminology
&lt;/h4&gt;

&lt;p&gt;GIT workflow is based on three main states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;&lt;i&gt;Committed&lt;/i&gt;&lt;/b&gt;: data is safely stored in your local database.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;&lt;i&gt;Modified&lt;/i&gt;&lt;/b&gt;: you changed your files but they are not yet added to your local database.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;&lt;i&gt;Staged&lt;/i&gt;&lt;/b&gt;: you marked a file in the current version to go into the next commit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following the previous definitions, three main working areas can be identified:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;&lt;i&gt;GIT directory&lt;/i&gt;&lt;/b&gt;: where GIT stores the metadata and the database for your project.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;&lt;i&gt;Staging area&lt;/i&gt;&lt;/b&gt;: this is a simple file, saved in the GIT directory, where GIT stores all the informations on what will go into your next commit.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;&lt;i&gt;Working directory&lt;/i&gt;&lt;/b&gt;: this is a single checkout of one version the project. The files are pulled out of the GIT directory and placed on disk for you to modify.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RR9NSLh1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.github.com/wildeng/articles-images/master/git-main-areas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RR9NSLh1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.github.com/wildeng/articles-images/master/git-main-areas.png" alt="svn manages changes"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;GIT main areas&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;From the picture above we can define how a typical GIT workflow looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You modify the files in your working directory.&lt;/li&gt;
&lt;li&gt;You stage them, adding a snapshot in the staging area&lt;/li&gt;
&lt;li&gt;You perform a commit which takes the snapshot from your staging area and stores it permanently in your GIT directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  GIT Objects
&lt;/h4&gt;

&lt;p&gt;What is the real heart of a GIT repository and which kind of objects GIT stores?&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;&lt;i&gt;object store&lt;/i&gt;&lt;/b&gt; is the correct answer, a database that holds four kind of items: &lt;i&gt;blobs, trees, commits and tags&amp;lt;/&amp;gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Blobs&lt;/i&gt;&lt;/b&gt; are a string of bytes with no further internal representation, as far as GIT is concerned. This does not mean that its implementation is simple. Every version of a file in GIT is represented with a blob where the entire content of the file is contained. If on one side this means occupying more space on disk, on the other side has the advantage of preventing corruption. If this happens on a blob, future versions of the file are not affected by it.&lt;/p&gt;

&lt;p&gt;A &lt;b&gt;&lt;i&gt;Tree&lt;/i&gt;&lt;/b&gt; represents a portion of the repository content at one point in time, a snapshot of a particular directory all its children included.&lt;/p&gt;

&lt;p&gt;A &lt;b&gt;&lt;i&gt;Commit&lt;/i&gt;&lt;/b&gt; is a snapshot of the entire repository content with additional data like identifying content such as author's name or committer's info, relationship of this state with all the other recorded states, providing an evolution of the repository over time.&lt;/p&gt;

&lt;p&gt;Specifically it is composed by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A pointer to a tree containing the complete state of the repository at one point in time.&lt;/li&gt;
&lt;li&gt;Author and committer information plus time and date the changes have been introduced.&lt;/li&gt;
&lt;li&gt;A list of zero or more objects, parents of the current commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;b&gt;&lt;i&gt;Tag&lt;/i&gt;&lt;/b&gt; is basically a commit with a human readable name in a namespace reserved for this purpose.&lt;/p&gt;

&lt;p&gt;It consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name of the person making the tag&lt;/li&gt;
&lt;li&gt;A timestamp&lt;/li&gt;
&lt;li&gt;A reference to the tagged commit&lt;/li&gt;
&lt;li&gt;A free-form text message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully you will now have appreciate the clever engineering that lies behind GIT curtains and also have a basic understanding of how it works.&lt;/p&gt;

&lt;p&gt;In the next posts I will try to explain some other related GIT arguments that I found useful and interesting like rewriting history. I will also share some nice and useful GIT commands I use day by day.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>git</category>
      <category>introduction</category>
      <category>newbie</category>
    </item>
    <item>
      <title>Dockerfile template for Rails Apps</title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Sun, 12 Jan 2020 17:21:18 +0000</pubDate>
      <link>https://dev.to/wildeng/dockerfile-template-for-rails-apps-3jde</link>
      <guid>https://dev.to/wildeng/dockerfile-template-for-rails-apps-3jde</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer:
&lt;/h2&gt;

&lt;p&gt;This post assumes that you know how Docker works and you know how to build images passing some arguments and that you know how to run a container.&lt;br&gt;
It's not and introduction to Docker.&lt;br&gt;
If you find any kind of error please contact me and I will amend the post.&lt;/p&gt;
&lt;h3&gt;
  
  
  Update:
&lt;/h3&gt;

&lt;p&gt;I've created a Github &lt;a href="https://github.com/wildeng/rails-docker-template"&gt;repo&lt;/a&gt; with some other stuff to support this post.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Dockerfile template for Rails apps
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Problem:
&lt;/h3&gt;

&lt;p&gt;I wanted to find a way to improve the on-boarding process of new developers joining my team and to improve the day to day life of my team's "legacy" developers. At that time, everyone had to manage different Ruby versions for different projects, manage different environment variables and so on. You can imagine how painful could have been such a process for a new developer in the team so, I started looking around for possible solutions.&lt;/p&gt;
&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;p&gt;After searching and reading a lot around, I came up with the conclusion that Docker could have been a good solution. &lt;br&gt;
Containers run in isolation, you can replicate a production environment, it runs on different systems and you can easily tweak it to test different features of your app. &lt;br&gt;
So everything seemed easy and pretty much working out of the box so, I came up with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;FROM ruby:2.5.3

&lt;span class="c"&gt;# The qq is for silent output in the console&lt;/span&gt;
RUN apt-get update &lt;span class="nt"&gt;-qq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential openssl libssl-dev nodejs-legacy less vim libsasl2-dev


&lt;span class="c"&gt;# Sets the path where the app is going to be installed&lt;/span&gt;
&lt;span class="c"&gt;# you can modify this as you wish&lt;/span&gt;
ENV WORK_ROOT /var
ENV RAILS_ROOT &lt;span class="nv"&gt;$WORK_ROOT&lt;/span&gt;/www/
ENV LANG C.UTF-8
ENV GEM_HOME &lt;span class="nv"&gt;$WORK_ROOT&lt;/span&gt;/bundle
ENV BUNDLE_BIN &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;/gems/bin
ENV PATH &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;/bin:&lt;span class="nv"&gt;$BUNDLE_BIN&lt;/span&gt;:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

RUN gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler &lt;span class="nt"&gt;-v&lt;/span&gt; 1.17.3

&lt;span class="c"&gt;# Creates the directory and all the parents (if they don't exist)&lt;/span&gt;
RUN &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

WORKDIR &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

&lt;span class="c"&gt;# We are copying the Gemfile first, so we can install&lt;/span&gt;
&lt;span class="c"&gt;# all the dependencies without any issues&lt;/span&gt;
&lt;span class="c"&gt;# Rails will be installed once you load it from the Gemfile&lt;/span&gt;
&lt;span class="c"&gt;# This will also ensure that gems are cached and only updated when&lt;/span&gt;
&lt;span class="c"&gt;# they change.&lt;/span&gt;
COPY Gemfile ./

&lt;span class="c"&gt;# Installs the Gem File.&lt;/span&gt;
RUN bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# We copy all the files from the current directory to our&lt;/span&gt;
&lt;span class="c"&gt;# application directory&lt;/span&gt;
COPY &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This was working fine for a while until one day... One day I decided that, because of the fact our production environment were Linux based, I wanted to go back to Linux and so, after giving back my Macbook Pro, I asked the company to provide me a Linux based machine.&lt;/p&gt;

&lt;p&gt;After setting it up properly, the easiest part should have been checking out the projects, starting up a container and done! Ready to go!&lt;/p&gt;

&lt;p&gt;No way!&lt;/p&gt;

&lt;p&gt;There was one point that I did not consider at that time. Macbooks are nice and shiny machines, but Docker runs on them in a virtual machine while in a Linux environment it runs as a daemon with root permissions...&lt;/p&gt;

&lt;p&gt;So the point is that, after running the container, all my files were "property" of the root user and I had to manually chmod then everytime.&lt;/p&gt;

&lt;p&gt;This was annoying and not the purpose of the entire effort. Anyway this problem can be easily overcome by passing some environment variables while building the image and creating a user that has the same gid and uid of the host user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ARG RUBY_VERSION
FROM ruby:&lt;span class="nv"&gt;$RUBY_VERSION&lt;/span&gt;

ARG BUNDLER_VERSION
ARG uid
ARG gid
&lt;span class="c"&gt;# The qq is for silent output in the console&lt;/span&gt;
RUN apt-get update &lt;span class="nt"&gt;-qq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential openssl libssl-dev nodejs-legacy less vim libsasl2-dev

&lt;span class="c"&gt;# To not run the container as root I create a users that shares&lt;/span&gt;
&lt;span class="c"&gt;# uid and gid with the host user.&lt;/span&gt;
&lt;span class="c"&gt;# In this way we can avoid having our working folder owned by root&lt;/span&gt;
RUN groupadd &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nv"&gt;$gid&lt;/span&gt; webuser
RUN useradd &lt;span class="nt"&gt;-ms&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$uid&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nv"&gt;$gid&lt;/span&gt; webuser

&lt;span class="c"&gt;# Sets the path where the app is going to be installed&lt;/span&gt;
ENV WORK_ROOT /var
ENV RAILS_ROOT &lt;span class="nv"&gt;$WORK_ROOT&lt;/span&gt;/www/
ENV LANG C.UTF-8
ENV GEM_HOME &lt;span class="nv"&gt;$WORK_ROOT&lt;/span&gt;/bundle
ENV BUNDLE_BIN &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;/gems/bin
ENV PATH &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;/bin:&lt;span class="nv"&gt;$BUNDLE_BIN&lt;/span&gt;:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

RUN gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$BUNDLER_VERSION&lt;/span&gt;

&lt;span class="c"&gt;# Creates the directory and all the parents (if they don't exist)&lt;/span&gt;
RUN &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

RUN &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; webuser:webuser &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;
RUN bundle config &lt;span class="nt"&gt;--path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;

WORKDIR &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

&lt;span class="c"&gt;# We are copying the Gemfile first, so we can install&lt;/span&gt;
&lt;span class="c"&gt;# all the dependencies without any issues&lt;/span&gt;
&lt;span class="c"&gt;# Rails will be installed once you load it from the Gemfile&lt;/span&gt;
&lt;span class="c"&gt;# This will also ensure that gems are cached and only updated when&lt;/span&gt;
&lt;span class="c"&gt;# they change.&lt;/span&gt;
COPY Gemfile ./
COPY Gemfile.lock ./

RUN &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; webuser:webuser &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

USER webuser
&lt;span class="c"&gt;# Installs the Gem File.&lt;/span&gt;
RUN bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# We copy all the files from the current directory to our&lt;/span&gt;
&lt;span class="c"&gt;# application directory&lt;/span&gt;
COPY &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;after doing it, I came up with a Dockerfile working on both Linux and MacOS machines (sorry Windows users I don't know if this works on your system).&lt;/p&gt;

&lt;p&gt;I also added some other environment variables like Ruby version, Bundler version that can be passed to Docker while building the image.&lt;/p&gt;

&lt;p&gt;You could think we're at the end, not at all. The company I'm working for uses LDAP so, uids and gids are big numbers and this carries a problem while creating the user in Docker I wasn't aware of. Basically if you add a user without &lt;code&gt;--no-log-init option&lt;/code&gt;, Docker will try to create lastlog as a massive sparse file that could easily eating your disk space.&lt;br&gt;
(more &lt;a href="https://github.com/moby/moby/issues/5419"&gt;here&lt;/a&gt; and &lt;a href="https://stackoverflow.com/questions/27701930/add-user-to-docker-container/57321205#57321205"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;So I ended up with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ARG RUBY_VERSION
FROM ruby:&lt;span class="nv"&gt;$RUBY_VERSION&lt;/span&gt;

ARG BUNDLER_VERSION
ARG uid
ARG gid
&lt;span class="c"&gt;# The qq is for silent output in the console&lt;/span&gt;
RUN apt-get update &lt;span class="nt"&gt;-qq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential openssl libssl-dev nodejs-legacy less vim libsasl2-dev

&lt;span class="c"&gt;# To not run the container as root I create a users that shares&lt;/span&gt;
&lt;span class="c"&gt;# uid and gid with the host user.&lt;/span&gt;
&lt;span class="c"&gt;# In this way we can avoid having our working folder owned by root&lt;/span&gt;
RUN groupadd &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nv"&gt;$gid&lt;/span&gt; webuser
RUN useradd &lt;span class="nt"&gt;--no-log-init&lt;/span&gt; &lt;span class="nt"&gt;-ms&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$uid&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nv"&gt;$gid&lt;/span&gt; webuser

&lt;span class="c"&gt;# Sets the path where the app is going to be installed&lt;/span&gt;
ENV WORK_ROOT /var
ENV RAILS_ROOT &lt;span class="nv"&gt;$WORK_ROOT&lt;/span&gt;/www/
ENV LANG C.UTF-8
ENV GEM_HOME &lt;span class="nv"&gt;$WORK_ROOT&lt;/span&gt;/bundle
ENV BUNDLE_BIN &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;/gems/bin
ENV PATH &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;/bin:&lt;span class="nv"&gt;$BUNDLE_BIN&lt;/span&gt;:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

RUN gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$BUNDLER_VERSION&lt;/span&gt;

&lt;span class="c"&gt;# Creates the directory and all the parents (if they don't exist)&lt;/span&gt;
RUN &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

RUN &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; webuser:webuser &lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;
RUN bundle config &lt;span class="nt"&gt;--path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$GEM_HOME&lt;/span&gt;

WORKDIR &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

&lt;span class="c"&gt;# We are copying the Gemfile first, so we can install&lt;/span&gt;
&lt;span class="c"&gt;# all the dependencies without any issues&lt;/span&gt;
&lt;span class="c"&gt;# Rails will be installed once you load it from the Gemfile&lt;/span&gt;
&lt;span class="c"&gt;# This will also ensure that gems are cached and only updated when&lt;/span&gt;
&lt;span class="c"&gt;# they change.&lt;/span&gt;
COPY Gemfile ./
COPY Gemfile.lock ./

RUN &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; webuser:webuser &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;

USER webuser
&lt;span class="c"&gt;# Installs the Gem File.&lt;/span&gt;
RUN bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# We copy all the files from the current directory to our&lt;/span&gt;
&lt;span class="c"&gt;# application directory&lt;/span&gt;
COPY &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$RAILS_ROOT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which is what I'm currently using.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>rails</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Find files between two dates</title>
      <dc:creator>Alain Mauri</dc:creator>
      <pubDate>Wed, 08 Jan 2020 21:20:58 +0000</pubDate>
      <link>https://dev.to/wildeng/find-files-between-two-dates-4g53</link>
      <guid>https://dev.to/wildeng/find-files-between-two-dates-4g53</guid>
      <description>&lt;h2&gt;
  
  
  Find files between two dates
&lt;/h2&gt;

&lt;p&gt;I’d like to share a simple way I’ve learned to find how many files have been created between two dates, using Linux command line. The method involves find command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Working on a project that involved the creation of a lot of &lt;a href="https://www.dicomobjects.com/tags/KOS"&gt;KOS&lt;/a&gt; objects (nothing difficult, just another &lt;a href="https://www.dicomlibrary.com/dicom/"&gt;DICOM&lt;/a&gt; object), I needed a quick and easy way to find out how many files my class method created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;I knew that find command could help, so I started digging into its manual and at the end I found the right option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nt"&gt;-newerXY&lt;/span&gt; reference
Succeeds &lt;span class="k"&gt;if &lt;/span&gt;timestamp X of the file being considered is newer than timestamp Y of the file reference. The letters X and Y can be any of the following letters:

              a   The access &lt;span class="nb"&gt;time &lt;/span&gt;of the file reference
              B   The birth &lt;span class="nb"&gt;time &lt;/span&gt;of the file reference
              c   The inode status change &lt;span class="nb"&gt;time &lt;/span&gt;of reference
              m   The modification &lt;span class="nb"&gt;time &lt;/span&gt;of the file reference
              t   reference is interpreted directly as a &lt;span class="nb"&gt;time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;after many trials I ended up with newermt which is newer with sub-options X=m for modification date and Y=t for literal time.&lt;/p&gt;

&lt;p&gt;At this point my “command” was taking shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.dcm"&lt;/span&gt; &lt;span class="nt"&gt;-newermt&lt;/span&gt; 2016-04-08 &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-newermt&lt;/span&gt; 2016-04-09
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Last thing I needed to know, was the number of files that have been created in the desired date interval and this was the easiest part of the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;the command used prints the newline count.&lt;/p&gt;

&lt;p&gt;Finally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.dcm"&lt;/span&gt; &lt;span class="nt"&gt;-newermt&lt;/span&gt; 2016-04-08 &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-newermt&lt;/span&gt; 2016-04-09 | &lt;span class="nb"&gt;wc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>commandline</category>
      <category>tricks</category>
    </item>
  </channel>
</rss>
