<?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: Nico Riedmann</title>
    <description>The latest articles on DEV Community by Nico Riedmann (@unseenwizzard).</description>
    <link>https://dev.to/unseenwizzard</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%2F174788%2Fc6a77d88-7bf4-41c0-8a97-fac421d88ae9.png</url>
      <title>DEV Community: Nico Riedmann</title>
      <link>https://dev.to/unseenwizzard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unseenwizzard"/>
    <language>en</language>
    <item>
      <title>Team Leadership Toolkit: Assessing risk</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Sun, 17 Sep 2023 19:37:40 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/team-leadership-toolkit-assessing-risk-4p5n</link>
      <guid>https://dev.to/unseenwizzard/team-leadership-toolkit-assessing-risk-4p5n</guid>
      <description>&lt;h1&gt;
  
  
  Team Leadership Toolkit: Assessing risk
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Unlike the previous TLTK articles, this one is pretty specific to my experience in software engineering and a "you build it, you run it" mindset in which teams are fully responsible for their software products working in production. &lt;br&gt;
If you're leading a team that's not responsible for operating something that is used by others, this likely won't be too helpful for you. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You might know this question. You might have heard it from your team as "Hey, everyone else took that week off, can I do as well?".&lt;br&gt;
Or from your lead as "What do we do if something fails while people are on vacation?".&lt;/p&gt;

&lt;p&gt;There are two pretty easy answers to that question of whether it's okay for &lt;em&gt;everyone&lt;/em&gt; to be off. &lt;br&gt;
Either it's a "No", or it's "Sure, it's Jane's on-call rotation week, though, so her vacation won't be great."&lt;/p&gt;

&lt;p&gt;Or if you're very confident, it might be, "Sure, nothing will happen!".&lt;br&gt;
Where's that confidence coming from though? Is it based on facts, or just your gut feeling?&lt;/p&gt;

&lt;p&gt;Even with an on-call rotation, are you sure that Jane can address &lt;em&gt;any&lt;/em&gt; issue that might come up?&lt;br&gt;
Especially if you happen to be on a team that owns several interconnected services, she might be missing something.&lt;/p&gt;

&lt;p&gt;One of the most useful tools I've found to answer this question is not my gut but taking a close look at risks and remediation strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collecting data
&lt;/h2&gt;

&lt;p&gt;To take a structured approach to this, let's start by collecting some basic data in your team's shared documentation tool of choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start by making a complete list of things your team is responsible for.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I'll be using 'thing' consistently. Your team might own several microservices, physical hardware, CI/CD pipelines, some internal dev tooling, etc. &lt;/p&gt;

&lt;p&gt;Whatever your 'things' may be, if someone calls you if they're having issues with it, write it on your list. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, for each of them, note down any &lt;strong&gt;known dependencies&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What do they depend on, and who owns it?

&lt;ul&gt;
&lt;li&gt;Note the thing and people responsible. In the best case, you can even link to their risk assessments.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;What depends on your thing, and who owns that?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Risk: How likely do things go wrong?
&lt;/h2&gt;

&lt;p&gt;We'll need that in a moment, but for now, let's collect some data about &lt;strong&gt;the stability of your thing&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many reported production issues did you have with this thing in the last month, quarter, and year?

&lt;ul&gt;
&lt;li&gt;You can probably pull that information from your ticketing system bug reports quite easily.&lt;/li&gt;
&lt;li&gt;Bonus points if you can find out if they usually relate to new releases or if there are other causes for people running into issues with your thing. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;What's the availability of your things in the last month, quarter, year?

&lt;ul&gt;
&lt;li&gt;If you don't yet track this, apply your team's collective gut-feeling or skip this for now. But do start thinking about how you'll know in the future. Consider that if your thing is running, but everything users do with it fails, it's not really available, so don't just track uptime.&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;With that, you should already be able to answer the question, "How likely is it that something will go wrong?".&lt;br&gt;
If your team owns more than one thing, each will of course, have a different likelihood of something going wrong - when thinking of the risk for your team, look at the most risky thing you own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impact: Just how bad will everyone's day be if things go wrong?
&lt;/h2&gt;

&lt;p&gt;The next part needs a bit more thinking and is a great exercise to do as the whole team: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What's the impact if your thing fails?&lt;/strong&gt; Do other things that depend on it fail as well? Are customers impacted? Are internal processes impacted? How important are those? Are there fallbacks or workarounds?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Remediation: What do you do when things go wrong?
&lt;/h2&gt;

&lt;p&gt;Still as a team, ask yourselves two more questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What can you do if your thing fails?&lt;/strong&gt; Are there several ways it might fail? Is it directly obvious something is wrong? What do you need to check what has gone wrong? What specific actions can you take to get your thing working again?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who can find out what's wrong and resolve the issue?&lt;/strong&gt; Does it need special knowledge only that one guy on your team has? Does it need specific tools or permissions, like access to a production database?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will likely show you a few things your gut feeling didn't.&lt;br&gt;
That super unstable thing you've been worried about can be fixed by restarting it, and because it happens a lot, there are many people allowed to do this.&lt;/p&gt;

&lt;p&gt;On the other hand, that thing you know is one of the most important ones in the company and is built well enough to only fail once in a blue moon, is so complex to fix that only the most senior engineer and your CTO know to troubleshoot what's wrong - after all they've built it years ago. And your CTO doesn't even have permission to access it anymore because he doesn't need it. &lt;/p&gt;

&lt;p&gt;Now, what do you do with all this information?&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with those facts
&lt;/h2&gt;

&lt;p&gt;For one, it helps you answer the "Can we all go on vacation for a month, and everything will just keep working?" question.&lt;/p&gt;

&lt;p&gt;If your experience is anything like mine, that answer will probably contradict your gut feeling and be some variation of "No. Nope. Never!".&lt;/p&gt;

&lt;p&gt;But the risk assessment exercise already gave you all the information you need to start working on making that answer a "Yes. For sure!".&lt;/p&gt;

&lt;p&gt;You know what things you actually need to focus your attention on and take steps to improve stability, simplify troubleshooting, and ensure everyone on your team has enough knowledge and can get the right access needed to solve problems if they should occur. &lt;/p&gt;

&lt;p&gt;And if "I want my whole team to go on vacation without worrying." is not a convincing enough argument to get improvements and knowledge-sharing time on your roadmap, "I want a consistent, high-quality experience for our customers with minimal issues and service interruptions." most certainly is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tWIx4MCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://riedmann.dev/img/tltk/risk-bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tWIx4MCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://riedmann.dev/img/tltk/risk-bg.png" alt="" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;There are a few reasonable followups to this exercise: &lt;/p&gt;

&lt;h3&gt;
  
  
  Think about your remediation strategies
&lt;/h3&gt;

&lt;p&gt;If you followed the steps, you've already started writing down what to do when things go wrong. Keep doing that and start thinking about how to make things easier to handle.&lt;/p&gt;

&lt;p&gt;Could your remediation steps be automated or at least simplified with scripts?&lt;/p&gt;

&lt;p&gt;If there are manual steps, can you turn them into well-defined &lt;a href="https://www.pagerduty.com/resources/learn/what-is-a-runbook/"&gt;playbooks and runbooks&lt;/a&gt; that anyone can follow?&lt;/p&gt;

&lt;h3&gt;
  
  
  Think about SLIs, SLOs and SLAs
&lt;/h3&gt;

&lt;p&gt;You might already be thinking to yourself, "Hey, this whole thing is just about defining SLOs!" - and at least one early reviewer did as well.&lt;/p&gt;

&lt;p&gt;I would argue it isn't. You can start taking a structured approach to risks without diving deep into SLOs, and you shouldn't ever feel like you need tooling in place before you can start thinking about risk.&lt;/p&gt;

&lt;p&gt;Yes, the two 'stability metrics' are very basic samples of service level indicators. But they're one's that make sense for most 'things' and for which you very likely have data available if you use any kind of issue management tool.&lt;/p&gt;

&lt;p&gt;That's what makes them a great starting point!&lt;/p&gt;

&lt;p&gt;As a next step, it might, of course, be time to find a way to measure more detailed SLIs and think about &lt;a href="https://cloud.google.com/blog/products/devops-sre/sre-fundamentals-sli-vs-slo-vs-sla"&gt;defining SLOs and SLAs&lt;/a&gt; based on the availability and the impact of downtimes you've discovered.&lt;/p&gt;




&lt;p&gt;The 'team leadership toolkit' is a series of bite-sized articles on techniques I find helpful as a software engineering team lead.&lt;/p&gt;

&lt;p&gt;Having shared most of this with peers and mentees in an unstructured way, I've started this to concisely describe the What, Why and How of things that work for me and might be helpful for others. &lt;/p&gt;

&lt;p&gt;What about you?  What's in your 'leadership toolkit'? &lt;br&gt;
I'd love to hear your comments or posts!&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Team Leadership Toolkit: Giving feedback</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Sun, 23 Jul 2023 10:33:00 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/team-leadership-toolkit-giving-feedback-17h7</link>
      <guid>https://dev.to/unseenwizzard/team-leadership-toolkit-giving-feedback-17h7</guid>
      <description>&lt;p&gt;One thing I keep learning is that giving feedback that works is all about clarity. &lt;/p&gt;

&lt;p&gt;This applies to praise as well as critical feedback but is especially important for the latter.&lt;/p&gt;

&lt;p&gt;Here are a few concepts I find helpful in delivering feedback :&lt;/p&gt;

&lt;h2&gt;
  
  
  "I" messages
&lt;/h2&gt;

&lt;p&gt;Giving "objective" feedback is hard and can lead you to state things as facts, that are really just your observation.&lt;/p&gt;

&lt;p&gt;It's not just more objective but also easier to clearly state your observations and feelings. &lt;/p&gt;

&lt;p&gt;Rather than assuming what effect someone's behaviour in a meeting had on a team, simply deliver how the situation impacted you and why the behaviour was not ok. &lt;/p&gt;

&lt;h2&gt;
  
  
  The SBI(TM) model - Situation, Behaviour, Impact, (Desire)
&lt;/h2&gt;

&lt;p&gt;A feedback model that lends itself to the idea above is Situation, Behaviour, Impact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;ituation - Clearly describe the situation the behaviour occurred in. When and where did this happen?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B&lt;/strong&gt;ehaviour - Clearly describe the behaviour you observed. Don't try to assume you know what the person was thinking or why they behaved that way, just describe what you saw.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I&lt;/strong&gt;mpact - Clearly describe the impact this behaviour had &lt;strong&gt;on you&lt;/strong&gt;. What did it make you feel or think?&lt;/p&gt;

&lt;p&gt;Usually clearly stating your feedback is enough to start a discussion on why this was not okay and how it can be improved. &lt;/p&gt;

&lt;p&gt;Ideas on what to change usually work a lot better when they come from the person receiving the feedback, but in some cases, I find it helpful to be specific on what needs to change:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D&lt;/strong&gt;esire - Clearly state what different behaviour you'll need to see the next time a similar situation occurs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timely feedback
&lt;/h2&gt;

&lt;p&gt;Receiving feedback works best (for me) if the situation is still fresh in my mind. As that's the case for most people, try and deliver feedback in a timely manner. &lt;/p&gt;

&lt;p&gt;Why "in a timely manner" and not just "immediately"? &lt;/p&gt;

&lt;p&gt;In general apply the "praise in public, critique in private" - calling someone out in front of a group will usually just result in a defensive reaction and can lead to bad team dynamics.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Depending on the behaviour you might need to call someone out on something as it happens, to stop it right away, but then deliver detailed feedback in private later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes neither you nor the receiver of feedback is in the right mental state for feedback - leave some room for moods to cool off or external stressful factors to pass, to ensure the feedback is delivered and received better.&lt;/p&gt;

&lt;p&gt;Just don't wait for your fixed cadence 1:1s or even yearly feedback/development talks to deliver feedback - by that time both you and the receiver of the feedback have probably forgotten the situation and why the feedback is important. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JLYIp6s7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://riedmann.dev/img/tltk/feedback.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JLYIp6s7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://riedmann.dev/img/tltk/feedback.png" alt="" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.radicalcandor.com/"&gt;Radical Candor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ccl.org/articles/leading-effectively-articles/closing-the-gap-between-intent-vs-impact-sbii/"&gt;Use Situation-Behavior-Impact (SBI)™ to Understand Intent&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The 'team leadership toolkit' is a series of bite-sized articles on techniques I find helpful as a software engineering team lead.&lt;/p&gt;

&lt;p&gt;Having shared most of this with peers and mentees in an unstructured way, I've started this to concisely describe the What, Why and How of things that work for me and might be helpful for others. &lt;/p&gt;

&lt;p&gt;What about you?  What's in your 'leadership toolkit'? &lt;br&gt;
I'd love to hear your comments or posts!&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>career</category>
    </item>
    <item>
      <title>Team Leadership Toolkit: Structured Career Development Overview</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Sun, 25 Jun 2023 13:11:06 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/team-leadership-toolkit-structured-career-development-overview-2hb</link>
      <guid>https://dev.to/unseenwizzard/team-leadership-toolkit-structured-career-development-overview-2hb</guid>
      <description>&lt;p&gt;Assuming you're already having frequent 1:1s and less-frequent longer feedback and career-development talks with your team members, it pays to keep a structured overview of everyone's goals, in-flight actions and your thoughts and notes in one place. &lt;/p&gt;

&lt;p&gt;Keeping this overview in a structured, shareable format like a wiki page achieves several things: &lt;br&gt;
1) It ensures you keep an overview of the full team - especially in larger teams, it is easy to focus on some remarkable people and lose sight of others.&lt;br&gt;
2) It helps you manage upwards - sharing the overview with your own direct lead makes it easy to keep them in the loop on team development, and allows them to notice and chime in early if development opportunities like new projects arise.&lt;/p&gt;

&lt;p&gt;To put this into practice you only need to do three things:&lt;/p&gt;

&lt;p&gt;1) Create a page in your favorite tool and add a table to track everything you want to track (see mine below).&lt;br&gt;
(For peak async communication share it with direct lead - and only them! - and send them a notification every time you update something.)&lt;br&gt;
2) Update it every time something new comes up - a reached milestone, relevant notes of a 1:1, a growth opportunity you just heard of, or that showerthought on how to help Alice become a great public speaker.&lt;br&gt;
3) Set aside half an hour every month to reflect on the overview - is there someone you didn't think about in a while, some actions you should follow up on, or some great achievement to keep in mind when it's time for promotions?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XwIOvklN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://riedmann.dev/img/tltk/personal_dev_overview.excalidraw.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XwIOvklN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://riedmann.dev/img/tltk/personal_dev_overview.excalidraw.svg" alt="Overview table of current roles, goals, actions and notes" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The 'team leadership toolkit' is a series of bite-sized articles on techniques I find helpful as a software engineering team lead.&lt;/p&gt;

&lt;p&gt;Having shared most of this with peers and mentees in an unstructured way, I've started this to concisely describe the What, Why and How of things that work for me and might be helpful for others. &lt;/p&gt;

&lt;p&gt;What about you?  What's in your 'leadership toolkit'? &lt;br&gt;
I'd love to hear your comments or posts!&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Team Leadership Toolkit: Two types of 1:1s</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Wed, 14 Jun 2023 10:49:57 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/team-leadership-toolkit-two-types-of-11s-1no5</link>
      <guid>https://dev.to/unseenwizzard/team-leadership-toolkit-two-types-of-11s-1no5</guid>
      <description>&lt;p&gt;A lot of great things have been written about 1:1s and giving feedback so if you want more, see the links at the end of this post!&lt;/p&gt;

&lt;p&gt;As you start having 1:1s with your team it can be difficult to decide on what exactly you should do in these meetings and how often to have them. Depending on your company there might be guidelines but they may be focusing on performance feedback and yearly review cycles.&lt;/p&gt;

&lt;p&gt;To me, there are two distinct types of 1:1 meetings you should have: &lt;/p&gt;

&lt;h2&gt;
  
  
  A frequent and short 1:1
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;~30 minutes on a 1-4 week cadence. (Start with a high frequency and reduce if it makes sense for both.)&lt;/li&gt;
&lt;li&gt;This is short-term and tactical - how is your team member doing and what do they need day-to-day?&lt;/li&gt;
&lt;li&gt;This is a space to give and get feedback and guidance, bring up anything else and get to know each other personally.&lt;/li&gt;
&lt;li&gt;This applies to both of you! This is the perfect place to ask for feedback on your leadership.&lt;/li&gt;
&lt;li&gt;Jointly own the agenda and possible notes in a privately shared place. (The image shows you a page structure I use for this.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A less frequent conversation on career development
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This one's probably defined by your company in some form.&lt;/li&gt;
&lt;li&gt;This is long-term and strategic - how is your team member fulfilling expectations, where do they want to go and how can you get there? &lt;/li&gt;
&lt;li&gt;This is the place to look back and discuss feedback, achievements, etc. as well as look forward and discuss goals, opportunities and how to get there. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither of these replaces giving feedback in a timely manner (don't wait for a 1:1 in three weeks to give feedback!) or looking at team-wide needs and improvements in retrospectives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ej0QbboI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/108k3w0z6jpzsecwtp1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ej0QbboI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/108k3w0z6jpzsecwtp1j.png" alt="1:1 overview" width="800" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://engineering.atspotify.com/2015/12/a-101-on-11s/"&gt;A 101 on 1:1s (Spotify blog)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boxofcrayons.com/the-coaching-habit-book/"&gt;The Coaching Habit: Say Less, Ask More &amp;amp; Change the Way You Lead Forever (book)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rework.withgoogle.com/guides/managers-coach-managers-to-coach/steps/coach-with-the-grow-model/"&gt;Coach with the GROW model (Google re:Work article)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The 'team leadership toolkit' is a series of bite-sized articles on techniques I find helpful as a software engineering team lead.&lt;/p&gt;

&lt;p&gt;Having shared most of this with peers and mentees in an unstructured way, I've started this to concisely describe the What, Why and How of things that work for me and might be helpful for others. &lt;/p&gt;

&lt;p&gt;What about you?  What's in your 'leadership toolkit'? &lt;br&gt;
I'd love to hear your comments or posts!&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>A Reading Habit - 2022 Reading List</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Tue, 27 Dec 2022 16:06:49 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/a-reading-habit-2022-reading-list-pme</link>
      <guid>https://dev.to/unseenwizzard/a-reading-habit-2022-reading-list-pme</guid>
      <description>&lt;h2&gt;
  
  
  A book-collecting habit
&lt;/h2&gt;

&lt;p&gt;I have always had a habit of &lt;em&gt;collecting&lt;/em&gt; books more than I managed to read them. &lt;/p&gt;

&lt;p&gt;In recent years that has only gotten worse with an ever-extending list of technical and work/leadership-related books finding a place next to existing stacks of fiction. &lt;/p&gt;

&lt;p&gt;In the past, I've tried things like moving the "to read" stack visibly onto my coffee table - until it got precariously unstable instead of any smaller - but never managed to read them faster than adding more.&lt;/p&gt;

&lt;p&gt;In spring 2022, I decided to take a page (pun very much intended) from one of the best books I read this year, and try "Making Work Visible".&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the Reading List visible
&lt;/h2&gt;

&lt;p&gt;I moved my collections of things I could read from places like Amazon wishlists and Goodreads into one Trello board, creating a prioritized list each for fiction and non-fiction/"professional learning".&lt;/p&gt;

&lt;p&gt;I even set myself a WIP limit of 1 learning and 1 entertainment book, to stop having several half-finished books.&lt;/p&gt;

&lt;p&gt;Which had the immediate effect of... changing nothing.&lt;/p&gt;

&lt;p&gt;But as I kept adding new interesting books to my list, it did one very important thing: it made it glaringly visible that I'll never get to read all the things I want to read if I don't start investing time in it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Making reading to learn things a habit
&lt;/h2&gt;

&lt;p&gt;Luckily my employer encourages professional development and sets an expectation to use a certain amount of hours for learning. &lt;/p&gt;

&lt;p&gt;So instead of starting my day by diving into slack, emails and anything I felt "urgently" needed to get done before standup, I've made it a habit to start my morning with a coffee and half an hour of reading. &lt;/p&gt;

&lt;p&gt;Of course, there are days when I don't manage - usually on office days when I already spend time just to get to work, or for the odd early meeting cutting into my morning. &lt;/p&gt;

&lt;p&gt;But still, I managed to read ten great books since early summer, some of which had been on the (re)reading list for quite a while (favorites in &lt;strong&gt;bold&lt;/strong&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The Mythical Man Month" by Fred Brooks&lt;/li&gt;
&lt;li&gt;"Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)" by Marianne Belloti&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Making Work Visible" by  Dominica DeGrandis&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;"The New One Minute Manager" by Ken Blanchard, Spencer johnson&lt;/li&gt;
&lt;li&gt;"The One Minute Manager Meets the Monkey" by Ken Blanchard, William Oncken Jr., Hal Burrows&lt;/li&gt;
&lt;li&gt;"Nonviolent Communication" by Marshall B. Rosenberg&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;"The Coaching Habit" by Michael Bungay Stanier&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Drive" by Daniel H. Pink&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;"The Culture Map" by Erin Meyer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Radical Candor" by Kim Scott&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Plus five fiction books, most memorably "The Night Watchman" by Louise Erdrich&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What have I learned this year?
&lt;/h2&gt;

&lt;p&gt;Making things you intend to do visible in one sorted place is incredibly valuable at showing not only the "work" but the impact of not doing it. &lt;/p&gt;

&lt;p&gt;If your focus tends to jump and you keep finding new things you want to do, read or learn about, setting a hard limit and sticking to is worth it.&lt;/p&gt;

&lt;p&gt;Take the time to learn and develop yourself and most importantly find the moment that works for you - for me the mornings before I get caught up in the tasks of the day is that time, while the end of the week is not. Any time to learn new things on Fridays I usually end up spending on things I still want to get done that week.&lt;/p&gt;

&lt;h2&gt;
  
  
  My New Year's Resolutions
&lt;/h2&gt;

&lt;p&gt;More strictly defend and take the time to read - which will likely mean a calendar entry blocking any early meetings and which gets moved to a later time in the morning for in-office days. &lt;/p&gt;

&lt;p&gt;Catch up on the technical reading list, as this year's list was mostly leadership-focused. (Which is off to an early start with "100 Go Mistakes and How to Avoid Them" by Teiva Harsanyi)&lt;/p&gt;

&lt;p&gt;Find more chances to discuss books with others. I only had the chance to read two books as part of book clubs this year, but the amount of perspective and insights these discussions add is invaluable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about you?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📚 What's the best book you read this year?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⏱️ How do you find the time to read?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>reading</category>
      <category>readinglist</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Automating presentations - from markdown to website</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Sat, 16 Jul 2022 19:11:42 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/automating-presentations-from-markdown-to-website-3fhh</link>
      <guid>https://dev.to/unseenwizzard/automating-presentations-from-markdown-to-website-3fhh</guid>
      <description>&lt;p&gt;Like many people I'm not a big fan of PowerPoint presentations. &lt;/p&gt;

&lt;p&gt;There's just too much to fuss about when creating slides in a WYSIWYG editor and while Office365 at least made it &lt;em&gt;possible&lt;/em&gt; to use PowerPoint as a Linux user, it's still far from a pleasant experience. &lt;/p&gt;

&lt;p&gt;When I work on a presentation I generally aim for slides that are simple - just a few words or images underlining what I say - and I want creating the to be just as simple. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: This won't work for you if you're presentation style relies on fancy slides with animations, etc. &lt;/p&gt;

&lt;p&gt;I've recently re-used a document of headlines meant to printed as 'slides' - something a friend very kindly described as a 'lean' approach to presentations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  The Idea
&lt;/h1&gt;

&lt;p&gt;My personal website is setup as a &lt;a href="https://pages.github.com/"&gt;GitHub Page&lt;/a&gt; which allows&lt;br&gt;
me to focus on content by turning text checked in to a GitHub repo&lt;br&gt;
into a static website using &lt;a href="https://jekyllrb.com/"&gt;jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As &lt;a href="https://riedmann.dev/2021/10/17/blog-automation-dev-to-posting.html"&gt;written about a while ago&lt;/a&gt; the content of my site and blog posts is simple markdown, so I'm quite used to formatting text with it.&lt;/p&gt;

&lt;p&gt;In the past I've used &lt;a href="https://marp.app/"&gt;marp - the Markdown Presentation Ecosystem&lt;/a&gt; to generate pdf slides from markdown.&lt;/p&gt;

&lt;p&gt;Which has the drawback of having to get that output file to wherever I want to present my slides from - you win that one Office365.&lt;/p&gt;

&lt;p&gt;But what if I could just write my slides in markdown, commit, push and have them available as part of my website? &lt;/p&gt;
&lt;h1&gt;
  
  
  Markdown Slides with Marp
&lt;/h1&gt;

&lt;p&gt;I won't go into detail on how to create Marp slides. &lt;/p&gt;

&lt;p&gt;If you want to know more checkout &lt;a href="https://marp.app/"&gt;marp.app&lt;/a&gt; and the docs on &lt;a href="https://marpit.marp.app/markdown"&gt;Marpit Markdown&lt;/a&gt; for details. &lt;/p&gt;

&lt;p&gt;I've created a simple sample slide deck with three slides. The comments in the snippet should tell you what you need to know for the sake of this post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;marp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;uncover&lt;/span&gt; 
&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invert&lt;/span&gt;
&lt;span class="c1"&gt;# Header configuring this as marp slides&lt;/span&gt;
&lt;span class="c1"&gt;# Theme and class simply defining my preferred dark theme for slides&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- A slide with a title --&amp;gt;&lt;/span&gt;
&lt;span class="gh"&gt;# These are some sample markdown slides&lt;/span&gt;
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Three dash breaks start a new slide --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- This one just has some text and a link --&amp;gt;&lt;/span&gt;

They're created using &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;marp&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://marp.app/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Another slide with some bullet points --&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;
*&lt;/span&gt; They're rendered from markdown to HTML using the &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;marp-cli docker container&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://hub.docker.com/r/marpteam/marp-cli/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.
&lt;span class="p"&gt;
*&lt;/span&gt; The rendered slides are deployed as part of my website.
&lt;span class="p"&gt;
*&lt;/span&gt; This happens in a &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;github action&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/UnseenWizzard/unseenwizzard.github.io/blob/8d812ca33bfac4106ddf5f58512740e925c835fa/.github/workflows/render-slides.yaml&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A note on Jekyll
&lt;/h2&gt;

&lt;p&gt;As mentioned I'm using a GitHub page and &lt;a href="https://jekyllrb.com/"&gt;jekyll&lt;/a&gt; for my website. &lt;/p&gt;

&lt;p&gt;In general &lt;a href="https://jekyllrb.com/"&gt;jekyll&lt;/a&gt; will take the markdown files from a &lt;code&gt;_posts&lt;/code&gt; directory and render them to html pages on my blog. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://jekyllrb.com/"&gt;jekyll&lt;/a&gt; will exclude any folders starting with an underscore from it's generated output, but it includes any other files and folders in the directory it's building. &lt;/p&gt;

&lt;p&gt;So to add my slides I've added a &lt;code&gt;_slides&lt;/code&gt; directory to place my markdown slides in. &lt;/p&gt;

&lt;p&gt;And we'll use marp to render them into a &lt;code&gt;slides&lt;/code&gt; directory - which means the final jekyll site will contain my slides at &lt;code&gt;{url}/slides/{filename}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating html pages with marp-cli
&lt;/h2&gt;

&lt;p&gt;Because I want to use this as part of a Github Action I'm using the &lt;a href="https://hub.docker.com/r/marpteam/marp-cli/"&gt;marp-cli docker container&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To turn my slides into html I simply run in the root path of my website repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;:/home/marp/app/ &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MARP_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; marpteam/marp-cli:v2.0.4 &lt;span class="nt"&gt;-I&lt;/span&gt; _slides/ &lt;span class="nt"&gt;-o&lt;/span&gt; slides/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mapping the current working directory into the container at &lt;code&gt;/home/marp/app&lt;/code&gt; with &lt;code&gt;-v $PWD:/home/marp/app/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensuring the cli can actually write files to the folder on linux, by telling to use the current user and group with &lt;code&gt;-e MARP_USER="$(id -u):$(id -g)"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;And finally running the CLI with the &lt;code&gt;_slides&lt;/code&gt; folder as input (&lt;code&gt;-I _slides/&lt;/code&gt;) and writing output to the &lt;code&gt;slides&lt;/code&gt; folder (&lt;code&gt;-o slides/&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;:/home/marp/app/ &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MARP_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; marpteam/marp-cli:v2.0.4 &lt;span class="nt"&gt;-I&lt;/span&gt; _slides/ &lt;span class="nt"&gt;-o&lt;/span&gt; slides/
&lt;span class="o"&gt;[&lt;/span&gt;  INFO &lt;span class="o"&gt;]&lt;/span&gt; Converting 3 markdowns...
&lt;span class="o"&gt;[&lt;/span&gt;  INFO &lt;span class="o"&gt;]&lt;/span&gt; _slides/agile-retrospective-design-patterns-short.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; slides/agile-retrospective-design-patterns-short.html
&lt;span class="o"&gt;[&lt;/span&gt;  INFO &lt;span class="o"&gt;]&lt;/span&gt; _slides/agile-retrospective-design-patterns.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; slides/agile-retrospective-design-patterns.html
&lt;span class="o"&gt;[&lt;/span&gt;  INFO &lt;span class="o"&gt;]&lt;/span&gt; _slides/sample-slides.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; slides/sample-slides.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Github Action
&lt;/h3&gt;

&lt;p&gt;As a Github Action step the same thing can be done as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Slides&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker://marpteam/marp-cli:v2.0.4&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-I _slides/ -o slides/&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;MARP_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root:root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Pushing the rendered pages to GitHub
&lt;/h1&gt;

&lt;p&gt;My website is rendered from the main branch of my github pages repository, so the files that &lt;code&gt;marp-cli&lt;/code&gt; just created need to get in there. &lt;/p&gt;

&lt;p&gt;Of course, I could just run the &lt;code&gt;marp-cli&lt;/code&gt; command after I change a slide deck and then commit and push the html page in addition to the markdown source - but I want to this to happen automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security trumps convenience
&lt;/h2&gt;

&lt;p&gt;As I don't want any random github action - or person - to push changes to my website, that main branch is protected.&lt;/p&gt;

&lt;p&gt;Meaning any change that's not from me will need to go through a Pull Request. &lt;br&gt;
This sadly adds a manual step of approving that PR which removes some of the 'fully automatic' convenience. &lt;/p&gt;
&lt;h2&gt;
  
  
  Pushing to a branch
&lt;/h2&gt;

&lt;p&gt;There's nothing special about pushing the new files using git. &lt;/p&gt;

&lt;p&gt;The step as defined below will use the fact that each github action run as a unique &lt;code&gt;run_id&lt;/code&gt; to create a unique branch to open a PR from.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Push to Branch&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;git config user.name 'marp slides build'&lt;/span&gt;
    &lt;span class="s"&gt;git config user.email '[my-user]@users.noreply.github.com'&lt;/span&gt;
    &lt;span class="s"&gt;git checkout -b "slides-${{github.run_id}}"&lt;/span&gt;
    &lt;span class="s"&gt;git commit -am "feat: Add rendered slides"&lt;/span&gt;
    &lt;span class="s"&gt;git push --set-upstream origin "slides-${{github.run_id}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a PR
&lt;/h2&gt;

&lt;p&gt;After wasting some time looking at GitHub Actions to open Pull Requests I decided to keep it simple and just use curl and &lt;a href="https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request"&gt;the GitHub API&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Open PR&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt; 
    &lt;span class="s"&gt;curl -X POST \&lt;/span&gt;
    &lt;span class="s"&gt;-f \&lt;/span&gt;
    &lt;span class="s"&gt;-H "Accept: application/vnd.github+json" \&lt;/span&gt;
    &lt;span class="s"&gt;-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \&lt;/span&gt;
    &lt;span class="s"&gt;https://api.github.com/repos/[my-user]/[my-gh-page-repo]/pulls \&lt;/span&gt;
    &lt;span class="s"&gt;-d '{"title":"Add rendered slides","body":"Adding rendered slides","head":"slides-${{github.run_id}}","base":"master"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which will result in curl doing a POST request to the GitHub API, authenticated with the github token that is passed to each GitHub Action - with the payload defining the PR title/body and most importantly which branches to merge. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-f&lt;/code&gt; (or &lt;code&gt;--fail&lt;/code&gt;) flag will ensure that curl will report a non-zero (failure) exit code if the HTTP call failed - which in turn results in the GitHub action showing as failed if something goes wrong. &lt;/p&gt;

&lt;h1&gt;
  
  
  The Result
&lt;/h1&gt;

&lt;p&gt;Putting it all together the full Action - configured to only run when changes to the &lt;code&gt;_slides&lt;/code&gt; are pushed, and first checking out the repo - looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;render-slides-with-marp&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_slides/**"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;render-slides&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Slides&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker://marpteam/marp-cli:v2.0.4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-I _slides/ --output slides/&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;MARP_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root:root&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Push to Branch&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name 'marp slides build'&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email '[my-user]@users.noreply.github.com'&lt;/span&gt;
          &lt;span class="s"&gt;git checkout -b "slides-${{github.run_id}}"&lt;/span&gt;
          &lt;span class="s"&gt;git add slides/&lt;/span&gt;
          &lt;span class="s"&gt;git commit -m "feat: Add rendered slides"&lt;/span&gt;
          &lt;span class="s"&gt;git push --set-upstream origin "slides-${{github.run_id}}"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Open PR&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt; 
          &lt;span class="s"&gt;curl   -X POST \&lt;/span&gt;
          &lt;span class="s"&gt;-f \&lt;/span&gt;
          &lt;span class="s"&gt;-H "Accept: application/vnd.github+json" \&lt;/span&gt;
          &lt;span class="s"&gt;-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \&lt;/span&gt;
          &lt;span class="s"&gt;https://api.github.com/repos/[my-user]/[my-gh-page-repo]/pulls \&lt;/span&gt;
          &lt;span class="s"&gt;-d '{"title":"Add rendered slides","body":"Adding rendered slides","head":"slides-${{github.run_id}}","base":"master"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quite simple for allowing me to create slide decks in markdown and the simply opening my website when I need them for a presentation.&lt;/p&gt;

&lt;p&gt;You can find the slides rendered from the sample above at &lt;a href="https://riedmann.dev/slides/sample-slides.html"&gt;riedmann.dev/slides/sample-slides.html&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I automated publishing my personal blog posts to dev.to</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Sun, 17 Oct 2021 17:51:50 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/how-i-automated-publishing-my-personal-blog-posts-to-devto-23l8</link>
      <guid>https://dev.to/unseenwizzard/how-i-automated-publishing-my-personal-blog-posts-to-devto-23l8</guid>
      <description>&lt;p&gt;I've recently decided to start writing again.&lt;/p&gt;

&lt;p&gt;And like most engineers I've immediately got down to... updating my website to&lt;br&gt;
contain a blog, and automating things like posting to other sites like dev.to.&lt;/p&gt;

&lt;p&gt;So to at least get &lt;em&gt;some&lt;/em&gt; writing done and share a bit of my workflow, here's&lt;br&gt;
how I've automated posting to dev.to using Github Actions.&lt;/p&gt;
&lt;h1&gt;
  
  
  The Idea
&lt;/h1&gt;

&lt;p&gt;My personal website is setup as a &lt;a href="https://pages.github.com/"&gt;GitHub Page&lt;/a&gt; which allows&lt;br&gt;
me to focus on content by turning text checked in to a GitHub repo&lt;br&gt;
into a static website using &lt;a href="https://jekyllrb.com/"&gt;jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Given that my blogposts are already written in markdown and dev.to offers an API that accepts&lt;br&gt;
markdown, publishing new posts to my personal website as well as dev.to seems easy.&lt;/p&gt;

&lt;p&gt;Simply take any new blog posts pushed to the GitHub repo, and send them to the dev.to API in addition to rendering my&lt;br&gt;
website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GqI2D1UB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://riedmann.dev/img/blog-automation/blog_automation_overview.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GqI2D1UB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://riedmann.dev/img/blog-automation/blog_automation_overview.svg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;image created with &lt;a href="//excalidraw.com"&gt;Excalidraw&lt;/a&gt; and the &lt;a href="https://libraries.excalidraw.com/?target=_excalidraw&amp;amp;referrer=https%3A%2F%2Fexcalidraw.com%2F&amp;amp;useHash=true&amp;amp;t%5Boken=WP8NRfaPj79aLbcdlm8CN&amp;amp;theme=light&amp;amp;sort=default#markopolo123-dev_ops"&gt;Dev Ops Icons&lt;/a&gt; library by &lt;a href="https://www.marksharpley.co.uk/"&gt;Mark Sharpley&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And because it seems so easy and I like things simple I've decided to make this work on my own using just Unix tools, git and curl instead of using an existing &lt;a href="https://github.com/features/actions"&gt;GitHub Action&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Finding new Blog Posts
&lt;/h1&gt;

&lt;p&gt;For the initial version of this I'm only interested in finding newly added blog posts on the main&lt;br&gt;
branch of my GitHub repo.&lt;/p&gt;

&lt;p&gt;Let's say the latest commit on the main branch was &lt;code&gt;aaaaaaa&lt;/code&gt; and I've just added two new posts and modified an old one in &lt;code&gt;bbbbbbb&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Just a &lt;code&gt;git diff&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A simple &lt;code&gt;git diff aaaaaaa bbbbbbb&lt;/code&gt; will show us the changes the between these two commits.&lt;/p&gt;

&lt;p&gt;But that's way to much, because all we care about are the type of modification and filename.&lt;/p&gt;

&lt;p&gt;Which &lt;code&gt;diff&lt;/code&gt; can luckily give us with a flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--name-status&lt;/span&gt; aaaaaaa bbbbbbb
M  _posts/2019-06-02-modified.md
A  _posts/2021-09-30-added.md
A  _posts/2021-10-17-added.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! One &lt;strong&gt;M&lt;/strong&gt;odified file and two &lt;strong&gt;A&lt;/strong&gt;dded files in &lt;code&gt;_posts/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But we still need to get this down to just the paths to new posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;sed&lt;/code&gt; to the Rescue
&lt;/h2&gt;

&lt;p&gt;To filter this down to just the filepaths of added posts, we'll use one of the more daunting Unix tools, the stream editor &lt;a href="https://www.gnu.org/software/sed/manual/sed.html"&gt;sed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll use it with a simple regex to transform the output of &lt;code&gt;git diff&lt;/code&gt; into a list of newly added blog posts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/A\s*\(_posts\/.*.md\)/\1/p'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple right? Let's quickly run through that line:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-n&lt;/code&gt; tells &lt;code&gt;sed&lt;/code&gt; to be 'silent'.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; operates per line, reading a line, performing operations and then printing/returning the edited line - unless told to be silent, which makes it print nothing unless told otherwise.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;p&lt;/code&gt; at the end of our commands tells it to print when the pattern was matched.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-e&lt;/code&gt; simply tells &lt;code&gt;sed&lt;/code&gt; explicitly that the next part is a command. We could omit this.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;s&lt;/strong&gt;ubstitution command that follows is the interesting part. It follows this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;s/[pattern to replace]/[what to replace it with]/[options]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's dissect how ours turns the input into just outputting the paths to any added files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s/A\s*\(_posts\/.*.md\)/\1/p`

&amp;gt; s/

Substitution command

&amp;gt; A\s*\(_posts\/.*.md\)

A         - lines starting with 'A'
\s*       - followed by zero or more whitespaces
_posts\/  - followed by '_posts/'
.*        - followed by zero or more characters
.md       - ending in .md
\(...\)   - captures what is between the braces to use again later

&amp;gt; \1

Simply references the content of the first capture group - the content of the braces above, which is our filepath.

&amp;gt; /p

Print the output of the substitution command.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Putting &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;sed&lt;/code&gt; together with a pipe (&lt;code&gt;|&lt;/code&gt;), we get what we need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--name-status&lt;/span&gt; aaaaaaa bbbbbbb | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/A\s*\(_posts\/.*.md\)/\1/p'&lt;/span&gt;
_posts/2021-09-30-added.md
_posts/2021-10-17-added.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Posting to dev.to
&lt;/h1&gt;

&lt;p&gt;Now that we have the markdown files of new posts, it's time to send them to dev.to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forem API
&lt;/h2&gt;

&lt;p&gt;dev.to uses &lt;a href="https://www.forem.com/"&gt;forem&lt;/a&gt; which offers a straight forward &lt;a href="https://developers.forem.com/api#operation/createArticle"&gt;articles API&lt;/a&gt; that accepts markdown with typical frontmatter directly.&lt;/p&gt;

&lt;p&gt;So in theory we can POST the contents of our markdown files straight to dev.to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wiremock for testing API integrations
&lt;/h3&gt;

&lt;p&gt;To test this - or any API - locally, &lt;a href="//wiremock.org."&gt;wiremock&lt;/a&gt; is a great tool.&lt;/p&gt;

&lt;p&gt;In standalone mode it can be run as a jar directly or using the &lt;a href="https://hub.docker.com/r/wiremock/wiremock/"&gt;docker container&lt;/a&gt;, and be configured using JSON to offer the endpoints you need and return what you want for testing.&lt;/p&gt;

&lt;p&gt;To test the basics of integrating with the forem API we'll do the following:&lt;/p&gt;

&lt;p&gt;Start the wiremock docker container in &lt;strong&gt;v&lt;/strong&gt;erbose mode, mapping it's default &lt;code&gt;8080&lt;/code&gt; port to the same port on our system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 wiremock/wiremock:latest &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then define a simple version of the articles API by sending it to the wiremock instance.&lt;/p&gt;

&lt;p&gt;For this we use &lt;code&gt;curl&lt;/code&gt; to call wiremock's API with JSON &lt;strong&gt;d&lt;/strong&gt;ata modelling the API endpoint we want to mock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl localhost:8080/__admin/mappings/new &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s1"&gt;'{
    "request": {
        "method": "POST",
        "url": "/api/articles"
    },
    "response": {
        "status": 200
    }
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;localhost:8080/api/articles&lt;/code&gt; will accept POST requests and always return a HTTP 200 response.&lt;/p&gt;

&lt;p&gt;Not really realistic, but a good start for testing, and seeing what payload arrives at the API, thanks to wiremock printing all calls it receives in verbose mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  POSTing Blog Posts
&lt;/h2&gt;

&lt;p&gt;To try out the local mock API we can send it a test payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl localhost:8080/api/articles &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"article": { "published": false, "body_markdown": "--- \n layout: post \n title: An automation test\n subtitle: a test subtitle\n---\n\n# Test content\n"} }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will POST an &lt;code&gt;article&lt;/code&gt; object - which could be completely defined with just it's &lt;code&gt;body_markdown&lt;/code&gt; as that already contains required information like the title, etc. in it's frontmatter.&lt;/p&gt;

&lt;p&gt;But as I want to be able to give posts a final look, the payload also includes &lt;code&gt;"published": false&lt;/code&gt; so posts will be created as a draft that can be published manually.&lt;/p&gt;

&lt;h1&gt;
  
  
  Putting it all together
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;git&lt;/code&gt; + &lt;code&gt;sed&lt;/code&gt; + &lt;code&gt;curl&lt;/code&gt; = &lt;code&gt;profit&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Time to put it all together, which I've done in a simple shell script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;
&lt;span class="nv"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$API_KEY&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Detecting files added between commits &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; and &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;

&lt;span class="nv"&gt;new_files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;git diff &lt;span class="nt"&gt;--name-status&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/A\s*\(_posts\/.*.md\)/\1/p'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;f &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$new_files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating dev.to article for &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;

    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"article": { "published": false, "body_markdown": "'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; api_payload
    &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;':a;N;$!ba;s/\n/\\n/g'&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; api_payload
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'" }}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; api_payload

    curl &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"api-key: &lt;/span&gt;&lt;span class="nv"&gt;$api_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; @api_payload &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-v&lt;/span&gt;

    &lt;span class="nb"&gt;rm &lt;/span&gt;api_payload
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a few more steps than just &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt; and &lt;code&gt;curl&lt;/code&gt; in there, so let's quickly run through them.&lt;/p&gt;

&lt;p&gt;The scripts will get the &lt;code&gt;URL&lt;/code&gt; and dev.to &lt;code&gt;API_KEY&lt;/code&gt; from environment variables, so they can be passed in from a GitHub Action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;
&lt;span class="nv"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$API_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it will find any &lt;code&gt;new_files&lt;/code&gt; between two commits that are passed in as first and second input arguments (&lt;code&gt;$1&lt;/code&gt; and &lt;code&gt;$2&lt;/code&gt;), and then post the content to the given &lt;code&gt;URL&lt;/code&gt; for each of the &lt;code&gt;new_files&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;new_files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;git diff &lt;span class="nt"&gt;--name-status&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$2&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s/A\s*\(_posts\/.*.md\)/\1/p'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;f &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$new_files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The body of the HTTP POST is placed in a temporary &lt;code&gt;api_payload&lt;/code&gt; file - but could also be built in place, or one long command piping into &lt;code&gt;curl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'{"article": { "published": false, "body_markdown": "'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; api_payload
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;':a;N;$!ba;s/\(["\\]\)/\\\1/g;s/\n/\\n/g;s/\t/  /g'&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; api_payload
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s1"&gt;'" }}'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; api_payload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only really interesting part of creating the payload is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;':a;N;$!ba;s/\(["\\]\)/\\\1/g;s/\n/\\n/g;s/\t/  /g'&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; api_payload&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; is used here to escape or replace special characters in the JSON payload.&lt;/p&gt;

&lt;p&gt;Double quotes and backslashes will be escaped with a backslash by the first substitution.&lt;/p&gt;

&lt;p&gt;The second substitution will replace newline in the markdown file with an escaped newline &lt;code&gt;\\n&lt;/code&gt;, so that the payload will actually contain &lt;code&gt;\n&lt;/code&gt; characters for each line break. Without this the API call would swallow all newlines and the blog post on dev.to would miss all linebreaks.&lt;/p&gt;

&lt;p&gt;The third substitution replaces tabs with two spaces rather than escaping them.&lt;/p&gt;

&lt;p&gt;How exactly that &lt;code&gt;sed&lt;/code&gt; expression replaces characters in the whole file is nicely described in &lt;a href="https://stackoverflow.com/a/1252191"&gt;this stakeoverflow post&lt;/a&gt;, so I will not repeat it here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; simply sends the json content of the temporary &lt;code&gt;api_payload&lt;/code&gt; file to the given &lt;code&gt;URL&lt;/code&gt; using the &lt;code&gt;API_KEY&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"api-key: &lt;/span&gt;&lt;span class="nv"&gt;$api_key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; @api_payload &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GitHub Action
&lt;/h2&gt;

&lt;p&gt;Now to have this script run whenever I add a new blog post to my website repo, we're still missing a GitHub action that calls it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post-to-dev-to&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_posts/**"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;post-to-dev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.github/workflows/dev-post.sh ${{ github.event.before}} ${{github.event.after}}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://dev.to/api/articles&lt;/span&gt;
          &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEV_TO_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because posting to dev.to should only happen for new posts I've pushed to the main branch of the repo, the Action is configured to only trigger if the &lt;code&gt;_posts/&lt;/code&gt; folder changes after a push to &lt;code&gt;master&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_posts/**"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the Action executes one job on an Ubuntu container, in which it first makes sure the repo is checked out, and then executes our script from above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;post-to-dev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.github/workflows/dev-post.sh ${{ github.event.before}} ${{github.event.after}}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://dev.to/api/articles&lt;/span&gt;
          &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEV_TO_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute the script is uses information from the &lt;code&gt;github.event&lt;/code&gt; that triggered the Action to get the latest commit &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; the push happened.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next?
&lt;/h1&gt;

&lt;p&gt;You're hopefully reading this on dev.to, proving this first part of blog automation has worked.&lt;/p&gt;

&lt;p&gt;If this is actually interesting to anyone I'll continue the series with a write-up on how I use markdown and GitHub actions to also create and publish slide-decks.&lt;/p&gt;

&lt;p&gt;Else I'll just continue my personal mission of only ever having to write markdown and wasting time on automation quietly and go back to writing about other things.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Being Agile about yourself - or the merits of small steps and frequent introspection</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Mon, 14 Oct 2019 20:13:49 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/being-agile-about-yourself-or-the-merits-of-small-steps-and-frequent-introspection-208e</link>
      <guid>https://dev.to/unseenwizzard/being-agile-about-yourself-or-the-merits-of-small-steps-and-frequent-introspection-208e</guid>
      <description>&lt;h1&gt;
  
  
  Introspection and me
&lt;/h1&gt;

&lt;p&gt;Introspection and self-reflection is something I first learned about and experienced when studying to be a teacher many years ago.&lt;/p&gt;

&lt;p&gt;I've long since adapted my plans and have been working in software engineering for the last three years, where the value of continuously taking a step back and evaluating what you are doing has become a core principle thanks to widespread Agile practices.&lt;/p&gt;

&lt;p&gt;But while regular reflection about work as a team in the form of Sprint Retrospectives has become the norm for me as a welcome chance to think about what went well, what didn't and how things could be improved, I haven't been spending any time on personal introspection until recently.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introspection and you
&lt;/h1&gt;

&lt;p&gt;Now whether you're a fan of Agile practices or not, you will probably agree that improving things that don't go well is something to strive for.&lt;/p&gt;

&lt;p&gt;On the flip-side if things go well, we enjoy hearing about that and might try to keep things as they are, so that more good things happen.&lt;/p&gt;

&lt;p&gt;A process of continuously looking at and evaluating what has happened allows us to do just that, no matter if it's done as part of a defined ceremony in a certain Agile framework, or just by taking five minutes each day to think back and reflect about what has happened.&lt;/p&gt;

&lt;h1&gt;
  
  
  But why?
&lt;/h1&gt;

&lt;p&gt;I've just started a new job that has a three week on-boarding process which covers everything from getting to know people, learning the basics of how things work at the company, and getting in-depth knowledge about and hands-on experience with working on the software product.&lt;/p&gt;

&lt;p&gt;Three weeks filled with &lt;em&gt;a lot&lt;/em&gt; of really interesting input.&lt;br&gt;
Early in the second week I've realized that while I did pay attention and even took notes of anything I found particularly interesting, it is so much input that days feel chaotic and somewhat exhausting. And on the following day even those notes I've scribbled down are too much to quickly glean the standout things.&lt;/p&gt;

&lt;p&gt;So how do you solve that if you already believe&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;taking your work in small, planned junks&lt;/li&gt;
&lt;li&gt;looking back to see if things are going well frequently&lt;/li&gt;
&lt;li&gt;making empirical decisions based on data&lt;/li&gt;
&lt;li&gt;improving things in small easy steps
is the most reasonable way to do your job?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You start doing just that, on a smaller personal scale day to day.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day Plan
&lt;/h1&gt;

&lt;p&gt;I started off by restarting something I've been doing on and off before:&lt;br&gt;
In the morning, before doing anything else, I write down my plan for the day.&lt;/p&gt;

&lt;p&gt;By not just keeping that plan in my head, I can not only check if I've actually done it, I also get the benefit of an immediate red flag if that list gets too long.&lt;/p&gt;

&lt;p&gt;If my coarse plan for today is half a page long, I probably won't be able to follow through on everything.&lt;/p&gt;

&lt;p&gt;That already gives me the chance to prioritize and cross things off which I don't actually &lt;em&gt;need&lt;/em&gt; to do that day, and which could distract me from the important things I might need to get finished soon.&lt;/p&gt;

&lt;p&gt;Additionally I find the act of physically crossing out things I've done to be immensely satisfying.&lt;/p&gt;

&lt;h1&gt;
  
  
  Daily Reflection
&lt;/h1&gt;

&lt;p&gt;Okay. Planned my day, great, we're done here!&lt;/p&gt;

&lt;p&gt;But things go as they usually go... not according to plan.&lt;/p&gt;

&lt;p&gt;So my day plan allows me to ask myself the first of the questions I currently ask myself at the end of every day:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Did my day go as planned?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And much more importantly than that binary question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If no, why not?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer might be obvious things like thinking I could accomplish more than I can actually fit in a day, but if that ends up being something that keeps happening frequently, it allows you to realize that you need to start thinking about the underlying issue.&lt;/p&gt;

&lt;p&gt;Maybe you're just bad at estimating, and should put less on your plate.&lt;br&gt;
Maybe there's some frequent distraction that you're not fully aware of, and that you can remedy once you are aware of it.&lt;/p&gt;

&lt;p&gt;Last week I've discovered that I failed to focus on a task I was working one, because waiting for a colleague to discuss something I went and started something else. &lt;br&gt;
A few days later I still had two half-finished things, where I could have finished one already, had I just 'annoyed' my colleague one more time and got the answers I needed more quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personal Questions
&lt;/h2&gt;

&lt;p&gt;Apart from the simple question that is directly linked to planning your day,anything else you might reflect on is highly personal and up to what you're currently focusing on, or trying to achieve.&lt;/p&gt;

&lt;p&gt;Currently I ask myself two additional questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Boyscout rule: Did I leave things/code better than I found them?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This relates to the fact that I currently try to apply the practices put forth by &lt;a href="https://clean-code-developer.com/"&gt;Clean Code Developer&lt;/a&gt; which is of course based on Robert C. Martin's Clean Code.&lt;/p&gt;

&lt;p&gt;And to my compulsion to improve things, which in the end is also what lead me to reflect regularly about what I'm doing and what can be improved.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What did I learn today?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one mainly relates to the fact that I've just started a new job, and serves to allow me to really pin down the important things to take away from every day.&lt;/p&gt;

&lt;h1&gt;
  
  
  Weekly Reflection
&lt;/h1&gt;

&lt;p&gt;A day is a short time-frame and I usually don't spend more than a few minutes thinking about my daily questions.&lt;/p&gt;

&lt;p&gt;But it's worth thinking about things on a larger timescale and distance, so I've started spending a bit more time at the end of the week to reflect on how it went.&lt;/p&gt;

&lt;h2&gt;
  
  
  My basic questions
&lt;/h2&gt;

&lt;p&gt;Like thinking about my daily plan, there's a few general questions I ask myself that I believe could be as useful to you, as they are to me.&lt;/p&gt;

&lt;p&gt;You also find these or similar questions mentioned in a lot of places, as of course they're very basic self-improvement questions. &lt;br&gt;
And they might just be what your team asks itself at the end of a sprint if you're applying Scrum.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What went well this week?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What didn't?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What to stop doing?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What to start doing?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What to keep doing?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see they simply focus on discovering what positive or negative things happened, and what to do about them.&lt;/p&gt;

&lt;p&gt;It might take some time and consideration to realize what specifically I want to stop or start doing in order to remedy the things that went badly in the prior week, but it is worth taking some time to think about that question, or even to just keep it in mind over the weekend.&lt;/p&gt;

&lt;p&gt;I generally find it easier to think about the positive things I want to keep doing. Generally these will be specific things that just pop into my head when I think about the question of what went well.&lt;/p&gt;

&lt;p&gt;For example it might be that I felt like I used my time much better since I started considering and writing down my daily plan again, so maybe I should just keep doing that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personal Questions
&lt;/h2&gt;

&lt;p&gt;Just like my daily reflection I use this to think about some more personal goals or problems, and so might you.&lt;br&gt;
Just find something that you feel is currently important.&lt;/p&gt;

&lt;p&gt;As an example I'll still tell you about mine:&lt;/p&gt;

&lt;p&gt;I was asked a while ago to think about my personal view of myself in very specific terms instead of general ones. Who do I want to be and Why? &lt;br&gt;
This is an exercise to aid in understanding what specific steps and goals there might be on the way to reaching that.&lt;/p&gt;

&lt;p&gt;One of the things I've realized, is that I still want to be a teacher. Not in the literal sense of standing in a school classroom, I stand by that decision.&lt;br&gt;
But I still enjoy learning new things, sharing those with people and helping them learn new things on their own.&lt;br&gt;
That realization is actually what triggered me to start writing articles like my git tutorial.&lt;/p&gt;

&lt;p&gt;The other is that I really like software development and I have somewhat high standards for myself and the work I do. So ideas about &lt;em&gt;software craftsmanship&lt;/em&gt; are something I value, &lt;em&gt;Clean Code&lt;/em&gt; is one of my favorite books and &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; has been on my reading list for way longer than it deserves.&lt;/p&gt;

&lt;p&gt;So from these realizations and wanting to constantly improve, I've added the following two question to think about every week:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What did you do towards being a professional software engineer?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What did you do towards being a teacher?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  What do you do?
&lt;/h1&gt;

&lt;p&gt;That's just what I've started doing though.&lt;/p&gt;

&lt;p&gt;I've written it down not only to allow myself to think it through in some more detail and share it with you hoping there's maybe some ideas in it that are interesting to you, but also to learn more about other people's habits and ideas.&lt;/p&gt;

&lt;p&gt;Do you follow a routine?&lt;br&gt;
Do you plan your day?&lt;br&gt;
Do you exercise introspection and how exactly do you do it?&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>motivation</category>
      <category>learning</category>
    </item>
    <item>
      <title>Do you know great Test Case/Suite tools (things like TestRail)?</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Tue, 04 Jun 2019 18:15:02 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/do-you-know-great-test-case-suite-tools-things-like-testrail-ojk</link>
      <guid>https://dev.to/unseenwizzard/do-you-know-great-test-case-suite-tools-things-like-testrail-ojk</guid>
      <description>&lt;p&gt;We're currently using TestRail to manage a somewhat large suite of manual and semi-automated tests, but we're not really happy with it. &lt;/p&gt;

&lt;p&gt;We sometimes remove test-cases, and it seems to only allow you to remove a test from a suite by also removing it from all previous test runs, so the history is gone... &lt;/p&gt;

&lt;p&gt;Things we just miss from TestRail are a way to integrate our semi-automatic tests in some way (e.g. automated setup via a script by clicking a button in the test tool), and having a history of changes for a test-case. &lt;/p&gt;

&lt;p&gt;Do you use some great test case tool or have another awesome way to deal with non-automated tests? &lt;br&gt;
Is it TestRail and we've just not really figured it out yet? &lt;/p&gt;

</description>
      <category>help</category>
      <category>discuss</category>
      <category>testing</category>
    </item>
    <item>
      <title>Learn git concepts, not commands</title>
      <dc:creator>Nico Riedmann</dc:creator>
      <pubDate>Sun, 02 Jun 2019 17:37:12 +0000</pubDate>
      <link>https://dev.to/unseenwizzard/learn-git-concepts-not-commands-4gjc</link>
      <guid>https://dev.to/unseenwizzard/learn-git-concepts-not-commands-4gjc</guid>
      <description>&lt;p&gt;&lt;strong&gt;An interactive git tutorial meant to teach you how git works, not just which commands to execute.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, you want to use git right? &lt;/p&gt;

&lt;p&gt;But you don't just want to learn commands, you want to understand what you're using? &lt;/p&gt;

&lt;p&gt;Then this is meant for you!&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Based on the general concept from Rachel M. Carmena's blog post on &lt;a href="https://rachelcarmena.github.io/2018/12/12/how-to-teach-git.html" rel="noopener noreferrer"&gt;How to teach Git&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While I find many git tutorials on the internet to be too focused on what to do instead of how things work, the most invaluable resource for both (and source for this tutorial!) are the &lt;a href="https://git-scm.com/book/en/v2" rel="noopener noreferrer"&gt;git Book&lt;/a&gt; and &lt;a href="https://git-scm.com/docs" rel="noopener noreferrer"&gt;Reference page&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So if you're still interested when you're done here, go check those out! I do hope the somewhat different concept of this tutorial will aid you in understanding all the other git features detailed there.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;
Getting a &lt;em&gt;Remote Repository&lt;/em&gt;

&lt;ul&gt;
&lt;li&gt;Adding new things&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Making changes&lt;/li&gt;

&lt;li&gt;Branching&lt;/li&gt;

&lt;li&gt;

Merging

&lt;ul&gt;
&lt;li&gt;Fast-Forward merging&lt;/li&gt;
&lt;li&gt;Merging divergent branches&lt;/li&gt;
&lt;li&gt;Resolving conflicts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Rebasing

&lt;ul&gt;
&lt;li&gt;Resolving conflicts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Updating the &lt;em&gt;Dev Environment&lt;/em&gt; with remote changes&lt;/li&gt;

&lt;li&gt;Cherry-picking&lt;/li&gt;

&lt;li&gt;Rewriting history&lt;/li&gt;

&lt;li&gt;Reading history&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In the picture below you see four boxes. One of them stands alone, while the other three are grouped together in what I'll call your &lt;em&gt;Development Environment&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fc6ya4uoag4i6uyay138i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fc6ya4uoag4i6uyay138i.png" alt="git components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll start with the one that's on it's own though. The &lt;em&gt;Remote Repository&lt;/em&gt; is where you send your changes when you want to share them with other people, and where you get their changes from. If you've used other version control systems there's nothing interesting about that. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Development Environment&lt;/em&gt; is what you have on your local machine. &lt;br&gt;
The three parts of it are your &lt;em&gt;Working Directory&lt;/em&gt;, the &lt;em&gt;Staging Area&lt;/em&gt; and the &lt;em&gt;Local Repository&lt;/em&gt;. We'll learn more about those as we start using git. &lt;/p&gt;

&lt;p&gt;Choose a place in which you want to put your &lt;em&gt;Development Environment&lt;/em&gt;. &lt;br&gt;
Just go to your home folder, or where ever you like to put your projects. You don't need to create a new folder for your &lt;em&gt;Dev Environment&lt;/em&gt; though. &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a &lt;em&gt;Remote Repository&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Now we want to grab a &lt;em&gt;Remote Repository&lt;/em&gt; and put what's in it onto your machine. &lt;/p&gt;

&lt;p&gt;I'd suggest we use this one (&lt;a href="https://github.com/UnseenWizzard/git_training.git" rel="noopener noreferrer"&gt;https://github.com/UnseenWizzard/git_training.git&lt;/a&gt; if you're not already reading this on github).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To do that I can use &lt;code&gt;git clone https://github.com/UnseenWizzard/git_training.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But as following this tutorial will need you to get the changes you make in your &lt;em&gt;Dev Environment&lt;/em&gt; back to the &lt;em&gt;Remote Repository&lt;/em&gt;, and github doesn't just allow anyone to do that to anyone's repo, you'll best create a &lt;em&gt;fork&lt;/em&gt; of it right now. There's a button to do that on the top right of this page. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that you have a copy of my &lt;em&gt;Remote Repository&lt;/em&gt; of your own, it's time to get that onto your machine. &lt;/p&gt;

&lt;p&gt;For that we use &lt;code&gt;git clone https://github.com/{YOUR USERNAME}/git_training.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the diagram below, this copies the &lt;em&gt;Remote Repository&lt;/em&gt; into two places, your &lt;em&gt;Working Directory&lt;/em&gt; and the &lt;em&gt;Local Repository&lt;/em&gt;. &lt;br&gt;
Now you see how git is &lt;em&gt;distributed&lt;/em&gt; version control. The &lt;em&gt;Local Repository&lt;/em&gt; is a copy of the &lt;em&gt;Remote&lt;/em&gt; one, and acts just like it. The only difference is that you don't share it with anyone. &lt;/p&gt;

&lt;p&gt;What &lt;code&gt;git clone&lt;/code&gt; also does, is create a new folder wherever you called it. There should be a &lt;code&gt;git_training&lt;/code&gt; folder now. Open it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbjel8pw6uf33msb71nsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbjel8pw6uf33msb71nsq.png" alt="Cloning the remote repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding new things
&lt;/h2&gt;

&lt;p&gt;Someone already put a file into the &lt;em&gt;Remote Repository&lt;/em&gt;. It's &lt;code&gt;Alice.txt&lt;/code&gt;, and kind of lonely there. Let's create a new file and call it &lt;code&gt;Bob.txt&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;What you've just done is add the file to your &lt;em&gt;Working Directory&lt;/em&gt;. &lt;br&gt;
There's two kinds of files in your &lt;em&gt;Working Directory&lt;/em&gt;: &lt;em&gt;tracked&lt;/em&gt; files that git knows about and &lt;em&gt;untracked&lt;/em&gt; files that git doesn't know about (yet). &lt;/p&gt;

&lt;p&gt;To see what's going on in your &lt;em&gt;Working Directory&lt;/em&gt; run &lt;code&gt;git status&lt;/code&gt;, which will tell you what branch you're on, whether your &lt;em&gt;Local Repository&lt;/em&gt; is different from the &lt;em&gt;Remote&lt;/em&gt; and the state of &lt;em&gt;tracked&lt;/em&gt; and &lt;em&gt;untracked&lt;/em&gt; files. &lt;/p&gt;

&lt;p&gt;You'll see that &lt;code&gt;Bob.txt&lt;/code&gt; is untracked, and &lt;code&gt;git status&lt;/code&gt; even tells you how to change that. &lt;br&gt;
In the picture below you can see what happens when you follow the advice and execute &lt;code&gt;git add Bob.txt&lt;/code&gt;: You've added the file to the &lt;em&gt;Staging Area&lt;/em&gt;, in which you collect all the changes you wish to put into &lt;em&gt;Repository&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fi24krafm0suo67y58dzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fi24krafm0suo67y58dzv.png" alt="Adding changes to the staging area"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you have added all your changes (which right now is only adding Bob), you're ready to &lt;em&gt;commit&lt;/em&gt; what you just did to the &lt;em&gt;Local Repository&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The collected changes that you &lt;em&gt;commit&lt;/em&gt; are some meaningful chunk of work, so when you now run &lt;code&gt;git commit&lt;/code&gt; a text editor will open and allow you to write a message telling everything what you just did. When you save and close the message file, your &lt;em&gt;commit&lt;/em&gt; is added to the &lt;em&gt;Local Repository&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2ex85fbz2mkvhjv8euww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2ex85fbz2mkvhjv8euww.png" alt="Committing to the local repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also add your &lt;em&gt;commit message&lt;/em&gt; right there in the command line if you call &lt;code&gt;git commit&lt;/code&gt; like this: &lt;code&gt;git commit -m "Add Bob"&lt;/code&gt;. But because you want to write &lt;a href="https://chris.beams.io/posts/git-commit/" rel="noopener noreferrer"&gt;good commit messages&lt;/a&gt; you really should take your time and use the editor.&lt;/p&gt;

&lt;p&gt;Now your changes are in your local repository, which is a good place for the to be as long as no one else needs them or you're not yet ready to share them. &lt;/p&gt;

&lt;p&gt;In order to share your commits with the &lt;em&gt;Remote Repository&lt;/em&gt; you need to &lt;code&gt;push&lt;/code&gt; them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Frbqwothmxs966mjj3z2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Frbqwothmxs966mjj3z2g.png" alt="Pushing to the local repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you run &lt;code&gt;git push&lt;/code&gt; the changes will be sent to the &lt;em&gt;Remote Repository&lt;/em&gt;. In the diagram below you see the state after your &lt;code&gt;push&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9l4l7d7d0088vkf1hdvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9l4l7d7d0088vkf1hdvc.png" alt="State of all components after pushing changes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Making changes
&lt;/h2&gt;

&lt;p&gt;So far we've only added a new file. Obviously the more interesting part of version control is changing files. &lt;/p&gt;

&lt;p&gt;Have a look at &lt;code&gt;Alice.txt&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It actually contains some text, but &lt;code&gt;Bob.txt&lt;/code&gt; doesn't, so lets change that and put &lt;code&gt;Hi!! I'm Bob. I'm new here.&lt;/code&gt; in there. &lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;git status&lt;/code&gt; now, you'll see that &lt;code&gt;Bob.txt&lt;/code&gt; is &lt;em&gt;modified&lt;/em&gt;. &lt;br&gt;
In that state the changes are only in your &lt;em&gt;Working Directory&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you want to see what has changed in your &lt;em&gt;Working Directory&lt;/em&gt; you can run &lt;code&gt;git diff&lt;/code&gt;, and right now see this: &lt;/p&gt;

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

diff --git a/Bob.txt b/Bob.txt
index e69de29..3ed0e1b 100644
--- a/Bob.txt
+++ b/Bob.txt
@@ -0,0 +1 @@
+Hi!! I'm Bob. I'm new here.


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

&lt;/div&gt;

&lt;p&gt;Go ahead and &lt;code&gt;git add Bob.txt&lt;/code&gt; like you've done before. As we know, this moves your changes to the &lt;em&gt;Staging Area&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;I want to see the changes we just &lt;em&gt;staged&lt;/em&gt;, so let's show the &lt;code&gt;git diff&lt;/code&gt; again! You'll notice that this time the output is empty. This happens because &lt;code&gt;git diff&lt;/code&gt; operates on the changes in your &lt;em&gt;Working Directory&lt;/em&gt; only. &lt;/p&gt;

&lt;p&gt;To show what changes are &lt;em&gt;staged&lt;/em&gt; already, we can use &lt;code&gt;git diff --staged&lt;/code&gt; and we'll see the same diff output as before. &lt;/p&gt;

&lt;p&gt;I just noticed that we put two exclamation marks after the 'Hi'. I don't like that, so lets change &lt;code&gt;Bob.txt&lt;/code&gt; again, so that it's just 'Hi!' &lt;/p&gt;

&lt;p&gt;If we now run &lt;code&gt;git status&lt;/code&gt; we'll see that there's two changes, the one we already &lt;em&gt;staged&lt;/em&gt; where we added text, and the one we just made, which is still only in the working directory. &lt;/p&gt;

&lt;p&gt;We can have a look at the &lt;code&gt;git diff&lt;/code&gt; between the &lt;em&gt;Working Directory&lt;/em&gt; and what we've already moved to the &lt;em&gt;Staging Area&lt;/em&gt;, to show what has changed since we last felt ready to &lt;em&gt;stage&lt;/em&gt; our changes for a &lt;em&gt;commit&lt;/em&gt;. &lt;/p&gt;

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

diff --git a/Bob.txt b/Bob.txt
index 8eb57c4..3ed0e1b 100644
--- a/Bob.txt
+++ b/Bob.txt
@@ -1 +1 @@
-Hi!! I'm Bob. I'm new here.
+Hi! I'm Bob. I'm new here.


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

&lt;/div&gt;

&lt;p&gt;As the change is what we wanted, let's &lt;code&gt;git add Bob.txt&lt;/code&gt; to stage the current state of the file. &lt;/p&gt;

&lt;p&gt;Now we're ready to &lt;code&gt;commit&lt;/code&gt; what we just did. I went with &lt;code&gt;git commit -m "Add text to Bob"&lt;/code&gt; because I felt for such a small change writing one line would be enough. &lt;/p&gt;

&lt;p&gt;As we know, the changes are now in the &lt;em&gt;Local Repository&lt;/em&gt;. &lt;br&gt;
We might still want to know what change we just &lt;em&gt;committed&lt;/em&gt; and what was there before. &lt;/p&gt;

&lt;p&gt;We can do that by comparing commits. &lt;br&gt;
Every commit in git has a unique hash by which it is referenced. &lt;/p&gt;

&lt;p&gt;If we have a look at the &lt;code&gt;git log&lt;/code&gt; we'll not only see a list of all the commits with their &lt;em&gt;hash&lt;/em&gt; as well as &lt;em&gt;Author&lt;/em&gt; and &lt;em&gt;Date&lt;/em&gt;, we also see the state of our &lt;em&gt;Local Repository&lt;/em&gt; and the latest local information about &lt;em&gt;remote branches&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Right now the &lt;code&gt;git log&lt;/code&gt; looks something like this: &lt;/p&gt;

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

commit 87a4ad48d55e5280aa608cd79e8bce5e13f318dc (HEAD -&amp;gt; master)
Author: {YOU} &amp;lt;{YOUR EMAIL}&amp;gt;
Date:   Sun Jan 27 14:02:48 2019 +0100

    Add text to Bob

commit 8af2ff2a8f7c51e2e52402ecb7332aec39ed540e (origin/master, origin/HEAD)
Author: {YOU} &amp;lt;{YOUR EMAIL}&amp;gt;
Date:   Sun Jan 27 13:35:41 2019 +0100

    Add Bob

commit 71a6a9b299b21e68f9b0c61247379432a0b6007c 
Author: UnseenWizzard &amp;lt;nicola.riedmann@live.de&amp;gt;
Date:   Fri Jan 25 20:06:57 2019 +0100

    Add Alice

commit ddb869a0c154f6798f0caae567074aecdfa58c46
Author: Nico Riedmann &amp;lt;UnseenWizzard@users.noreply.github.com&amp;gt;
Date:   Fri Jan 25 19:25:23 2019 +0100

    Add Tutorial Text

      Changes to the tutorial are all squashed into this commit on master, to keep the log free of clutter that distracts from the tutorial

      See the tutorial_wip branch for the actual commit history


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

&lt;/div&gt;

&lt;p&gt;In there we see a few interesting things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first two commits are made by me.&lt;/li&gt;
&lt;li&gt;Your initial commit to add Bob is the current &lt;em&gt;HEAD&lt;/em&gt; of the &lt;em&gt;master&lt;/em&gt; branch on the &lt;em&gt;Remote Repository&lt;/em&gt;. We'll look at this again when we talk about branches and getting remote changes.&lt;/li&gt;
&lt;li&gt;The latest commit in the &lt;em&gt;Local Repository&lt;/em&gt; is the one we just made, and now we know its hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that the actual commit hashes will be different for you. If you want to know how exactly git arrives at those revision IDs have a look at &lt;a href="https://blog.thoughtram.io/git/2014/11/18/the-anatomy-of-a-git-commit.html" rel="noopener noreferrer"&gt;this interesting article &lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To compare that commit and the one one before we can do &lt;code&gt;git diff &amp;lt;commit&amp;gt;^!&lt;/code&gt;, where the &lt;code&gt;^!&lt;/code&gt; tells git to compare to the commit one before. So in this case I run &lt;code&gt;git diff 87a4ad48d55e5280aa608cd79e8bce5e13f318dc^!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can also do &lt;code&gt;git diff 8af2ff2a8f7c51e2e52402ecb7332aec39ed540e 87a4ad48d55e5280aa608cd79e8bce5e13f318dc&lt;/code&gt; for the same result and in general to compare any two commits. Note that the format here is &lt;code&gt;git diff &amp;lt;from commit&amp;gt; &amp;lt;to commit&amp;gt;&lt;/code&gt;, so our new commit comes second.&lt;/p&gt;

&lt;p&gt;In the diagram below you again see the different stages of a change, and the diff commands that apply to where a file currently is. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzkxplgab8ye71b660fxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzkxplgab8ye71b660fxj.png" alt="States of a change an related diff commands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we're sure we made the change we wanted, go ahead and &lt;code&gt;git push&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Branching
&lt;/h2&gt;

&lt;p&gt;Another thing that makes git great, is the fact that working with branches is really easy and integral part of how you work with git.&lt;/p&gt;

&lt;p&gt;In fact we've been working on a branch since we've started.&lt;/p&gt;

&lt;p&gt;When you &lt;code&gt;clone&lt;/code&gt; the &lt;em&gt;Remote Repository&lt;/em&gt; your &lt;em&gt;Dev Environment&lt;/em&gt; automatically starts on the repositories main or &lt;em&gt;master&lt;/em&gt; branch.&lt;/p&gt;

&lt;p&gt;Most work-flows with git include making your changes on a &lt;em&gt;branch&lt;/em&gt;, before you &lt;code&gt;merge&lt;/code&gt; them back into &lt;em&gt;master&lt;/em&gt;. &lt;br&gt;
Usually you'll be working on your own &lt;em&gt;branch&lt;/em&gt;, until you're done and confident in your changes which can then be merged into the &lt;em&gt;master&lt;/em&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Many git repository managers like &lt;em&gt;GitLab&lt;/em&gt; and &lt;em&gt;GitHub&lt;/em&gt; also allow for branches to be &lt;em&gt;protected&lt;/em&gt;, which means that not everyone is allowed to just &lt;code&gt;push&lt;/code&gt; changes there. There the &lt;em&gt;master&lt;/em&gt; is usually protected by default. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don't worry, we'll get back to all of these things in more detail when we need them.  &lt;/p&gt;

&lt;p&gt;Right now we want to create a branch to make some changes there. Maybe you just want to try something on your own and not mess with the working state on your &lt;em&gt;master&lt;/em&gt; branch, or you're not allowed to &lt;code&gt;push&lt;/code&gt; to &lt;em&gt;master&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Branches live in the &lt;em&gt;Local&lt;/em&gt; and &lt;em&gt;Remote Repository&lt;/em&gt;. When you create a new branch, the branches contents will be a copy of the currently committed state of whatever branch you are currently working on. &lt;/p&gt;

&lt;p&gt;Let's make some change to &lt;code&gt;Alice.txt&lt;/code&gt;! How about we put some text on the second line?  &lt;/p&gt;

&lt;p&gt;We want to share that change, but not put it on &lt;em&gt;master&lt;/em&gt; right away, so let's create a branch for it using &lt;code&gt;git branch &amp;lt;branch name&amp;gt;&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To create a new branch called &lt;code&gt;change_alice&lt;/code&gt; you can run &lt;code&gt;git branch change_alice&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This adds the new branch to the &lt;em&gt;Local Repository&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;While your &lt;em&gt;Working Directory&lt;/em&gt; and &lt;em&gt;Staging Area&lt;/em&gt; don't really care about branches, you always &lt;code&gt;commit&lt;/code&gt; to the branch you are currently on. &lt;/p&gt;

&lt;p&gt;You can think of &lt;em&gt;branches&lt;/em&gt; in git as pointers, pointing to a series of commits. When you &lt;code&gt;commit&lt;/code&gt;, you add to whatever you're currently pointing to. &lt;/p&gt;

&lt;p&gt;Just adding a branch, doesn't directly take you there, it just creates such a pointer. &lt;br&gt;
In fact the state your &lt;em&gt;Local Repository&lt;/em&gt; is currently at, can be viewed as another pointer, called &lt;em&gt;HEAD&lt;/em&gt;, which points to what branch and commit you are currently at. &lt;/p&gt;

&lt;p&gt;If that sounds complicated the diagrams below will hopefully help to clear things up a bit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fd1ctq2t2a590hepqxlum.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fd1ctq2t2a590hepqxlum.png" alt="State after adding branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To switch to our new branch you will have to use &lt;code&gt;git checkout change_alice&lt;/code&gt;. What this does is simply to move the &lt;em&gt;HEAD&lt;/em&gt; to the branch you specify.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As you'll usually want switch to a branch right after creating it, there is the convenient &lt;code&gt;-b&lt;/code&gt; option available for the &lt;code&gt;checkout&lt;/code&gt; command, which allows you to just directly &lt;code&gt;checkout&lt;/code&gt; a &lt;em&gt;new&lt;/em&gt; branch, so you don't have to create it beforehand. &lt;/p&gt;

&lt;p&gt;So to create and switch to our &lt;code&gt;change_alice&lt;/code&gt; branch, we could also just have called &lt;code&gt;git checkout -b change_alice&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxzhd1nin8uw05fvkox8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxzhd1nin8uw05fvkox8d.png" alt="State after after switching branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll notice that your &lt;em&gt;Working Directory&lt;/em&gt; hasn't changed. That we've &lt;em&gt;modified&lt;/em&gt; &lt;code&gt;Alice.txt&lt;/code&gt; is not related to the branch we're on yet. &lt;br&gt;
Now you can &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;commit&lt;/code&gt; the change to &lt;code&gt;Alice.txt&lt;/code&gt; just like we did on the &lt;em&gt;master&lt;/em&gt; before, which will &lt;em&gt;stage&lt;/em&gt; (at which point it's still unrelated to the branch) and finally &lt;em&gt;commit&lt;/em&gt; your change to the &lt;code&gt;change_alice&lt;/code&gt; branch. &lt;/p&gt;

&lt;p&gt;There's just one thing you can't do yet. Try to &lt;code&gt;git push&lt;/code&gt; your changes to the &lt;em&gt;Remote Repository&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You'll see the following error and - as git is always ready to help - a suggestion how to resolve the issue: &lt;/p&gt;

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

fatal: The current branch change_alice has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin change_alice 


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

&lt;/div&gt;

&lt;p&gt;But we don't just want to blindly do that. We're here to understand what's actually going on. So what are &lt;em&gt;upstream branches&lt;/em&gt; and &lt;em&gt;remotes&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Remember when we &lt;code&gt;cloned&lt;/code&gt; the &lt;em&gt;Remote Repository&lt;/em&gt; a while ago? At that point it didn't only contain this tutorial and &lt;code&gt;Alice.txt&lt;/code&gt; but actually two branches. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;master&lt;/em&gt; we just went ahead and started working on, and one I called "tutorial_wip" on which I commit all the changes I make to this tutorial. &lt;/p&gt;

&lt;p&gt;When we copied the things in the &lt;em&gt;Remote Repository&lt;/em&gt; into your &lt;em&gt;Dev Environment&lt;/em&gt; a few extra steps happened under the hood. &lt;/p&gt;

&lt;p&gt;Git setup the &lt;em&gt;remote&lt;/em&gt; of your &lt;em&gt;Local Repository&lt;/em&gt; to be the &lt;em&gt;Remote Repository&lt;/em&gt; you cloned and gave it the default name &lt;code&gt;origin&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your &lt;em&gt;Local Repository&lt;/em&gt; can track several &lt;em&gt;remotes&lt;/em&gt; and they can have different names, but we'll stick to the &lt;code&gt;origin&lt;/code&gt; and nothing else for this tutorial. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then it copied the two remote branches into your &lt;em&gt;Local Repository&lt;/em&gt; and finally it &lt;code&gt;checked out&lt;/code&gt; &lt;em&gt;master&lt;/em&gt; for you. &lt;/p&gt;

&lt;p&gt;When doing that another implicit step happens. When you &lt;code&gt;checkout&lt;/code&gt; a branch name that has an exact match in the remote branches, you will get a new &lt;em&gt;local&lt;/em&gt; branch that is linked to the &lt;em&gt;remote&lt;/em&gt; branch. The &lt;em&gt;remote&lt;/em&gt; branch is the &lt;em&gt;upstream branch&lt;/em&gt; of your &lt;em&gt;local&lt;/em&gt; one. &lt;/p&gt;

&lt;p&gt;In the diagrams above you can see just the local branches you have. You can see that list of local branches by running &lt;code&gt;git branch&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you want to also see the &lt;em&gt;remote&lt;/em&gt; branches your &lt;em&gt;Local Repository&lt;/em&gt; knows, you can use &lt;code&gt;git branch -a&lt;/code&gt; to list all of them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjhorb5a37poy1nwu284p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjhorb5a37poy1nwu284p.png" alt="Remote and local branches"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can call the suggested &lt;code&gt;git push --set-upstream origin change_alice&lt;/code&gt;, and &lt;code&gt;push&lt;/code&gt; the changes on our branch to a new &lt;em&gt;remote&lt;/em&gt;. This will create a &lt;code&gt;change_alice&lt;/code&gt; branch on the &lt;em&gt;Remote Repository&lt;/em&gt; and set our &lt;em&gt;local&lt;/em&gt; &lt;code&gt;change_alice&lt;/code&gt; to track that new branch. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is another option if we actually want our branch to track something that already exists on the &lt;em&gt;Remote Repository&lt;/em&gt;. Maybe a colleague has already pushed some changes, while we were working on something related on our local branch, and we'd like to integrate the two. Then we could just set the &lt;em&gt;upstream&lt;/em&gt; for our &lt;code&gt;change_alice&lt;/code&gt; branch to a new &lt;em&gt;remote&lt;/em&gt; by using &lt;code&gt;git branch --set-upstream-to=origin/change_alice&lt;/code&gt; and from there on track the &lt;em&gt;remote&lt;/em&gt; branch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that went through have a look at your &lt;em&gt;Remote Repository&lt;/em&gt; on github, your branch will be there, ready for other people to see and work with. &lt;/p&gt;

&lt;p&gt;We'll get to how you can get other people's changes into your &lt;em&gt;Dev Environment&lt;/em&gt; soon, but first we'll work a bit more with branches, to introduce all the concepts that also come into play when we get new things from the &lt;em&gt;Remote Repository&lt;/em&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Merging
&lt;/h2&gt;

&lt;p&gt;As you and everyone else will generally be working on branches, we need to talk about how to get changes from one branch into the other by &lt;em&gt;merging&lt;/em&gt; them. &lt;/p&gt;

&lt;p&gt;We've just changed &lt;code&gt;Alice.txt&lt;/code&gt; on the &lt;code&gt;change_alice&lt;/code&gt; branch, and I'd say we're happy with the changes we made. &lt;/p&gt;

&lt;p&gt;If you go and &lt;code&gt;git checkout master&lt;/code&gt;, the &lt;code&gt;commit&lt;/code&gt; we made on the other branch will not be there. To get the changes into master we need to &lt;code&gt;merge&lt;/code&gt; the &lt;code&gt;change_alice&lt;/code&gt; branch &lt;em&gt;into&lt;/em&gt; master. &lt;/p&gt;

&lt;p&gt;Note that you always &lt;code&gt;merge&lt;/code&gt; some branch &lt;em&gt;into&lt;/em&gt; the one you're currently at. &lt;/p&gt;

&lt;h3&gt;
  
  
  Fast-Forward merging
&lt;/h3&gt;

&lt;p&gt;As we've already &lt;code&gt;checked out&lt;/code&gt; master, we can now &lt;code&gt;git merge change_alice&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;As there are no other &lt;em&gt;conflicting&lt;/em&gt; changes to &lt;code&gt;Alice.txt&lt;/code&gt;, and we've changed nothing on &lt;em&gt;master&lt;/em&gt;, this will go through without a hitch in what is called a &lt;em&gt;fast forward&lt;/em&gt; merge. &lt;/p&gt;

&lt;p&gt;In the diagrams below, you can see that this just means that the &lt;em&gt;master&lt;/em&gt; pointer can simply be advanced to where the &lt;em&gt;change_alice&lt;/em&gt; one already is. &lt;/p&gt;

&lt;p&gt;The first diagram shows the state before our &lt;code&gt;merge&lt;/code&gt;, &lt;em&gt;master&lt;/em&gt; is still at the commit it was, and on the other branch we've made one more commit. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxjq4fxj3k67i9g2b98a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxjq4fxj3k67i9g2b98a3.png" alt="Before fast forward merge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second diagram shows what has changed with our &lt;code&gt;merge&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F23qryu4234bs0f4k10rm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F23qryu4234bs0f4k10rm.png" alt="After fast forward merge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Merging divergent branches
&lt;/h3&gt;

&lt;p&gt;Let's try something more complex. &lt;/p&gt;

&lt;p&gt;Add some text on a new line to &lt;code&gt;Bob.txt&lt;/code&gt; on &lt;em&gt;master&lt;/em&gt; and commit it. &lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;git checkout change_alice&lt;/code&gt;, change &lt;code&gt;Alice.txt&lt;/code&gt; and commit. &lt;/p&gt;

&lt;p&gt;In the diagram below you see how our commit history now looks. Both &lt;em&gt;master&lt;/em&gt; and &lt;code&gt;change_alice&lt;/code&gt; originated from the same commit, but since then they &lt;em&gt;diverged&lt;/em&gt;, each having their own additional commit. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpt7yj49d64hkt5rnm2eh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpt7yj49d64hkt5rnm2eh.png" alt="Divergent commits"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you now &lt;code&gt;git merge change_alice&lt;/code&gt; a fast-forward merge is not possible. Instead your favorite text editor will open and allow you to change the message of the &lt;code&gt;merge commit&lt;/code&gt; git is about to make in order to get the two branches back together. You can just go with the default message right now. The diagram below shows the state of our git history after we the &lt;code&gt;merge&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fns2g50cds1261ybl7zvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fns2g50cds1261ybl7zvb.png" alt="Merging branches"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new commit introduces the changes that we've made on the &lt;code&gt;change_alice&lt;/code&gt; branch into master. &lt;/p&gt;

&lt;p&gt;As you'll remember from before, revisions in git, aren't only a snapshot of your files but also contain information on where they came from from. Each &lt;code&gt;commit&lt;/code&gt; has one or more parent commits. Our new &lt;code&gt;merge&lt;/code&gt; commit, has both the last commit from &lt;em&gt;master&lt;/em&gt; and the commit we made on the other branch as it's parents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolving conflicts
&lt;/h3&gt;

&lt;p&gt;So far our changes haven't interfered with each other. &lt;/p&gt;

&lt;p&gt;Let's introduce a &lt;em&gt;conflict&lt;/em&gt; and then &lt;em&gt;resolve&lt;/em&gt; it. &lt;/p&gt;

&lt;p&gt;Create and &lt;code&gt;checkout&lt;/code&gt; a new branch. You know how, but maybe try using &lt;code&gt;git checkout -b&lt;/code&gt; to make your live easier. &lt;br&gt;
I've called mine &lt;code&gt;bobby_branch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the branch we'll make a change to &lt;code&gt;Bob.txt&lt;/code&gt;. &lt;br&gt;
The first line should still be &lt;code&gt;Hi!! I'm Bob. I'm new here.&lt;/code&gt;. Change that to &lt;code&gt;Hi!! I'm Bobby. I'm new here.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Stage and then &lt;code&gt;commit&lt;/code&gt; your change, before you &lt;code&gt;checkout&lt;/code&gt; &lt;em&gt;master&lt;/em&gt; again. Here we'll change that same line to &lt;code&gt;Hi!! I'm Bob. I've been here for a while now.&lt;/code&gt; and &lt;code&gt;commit&lt;/code&gt; your change. &lt;/p&gt;

&lt;p&gt;Now it's time to &lt;code&gt;merge&lt;/code&gt; the new branch into &lt;em&gt;master&lt;/em&gt;. &lt;br&gt;
When you try that, you'll see the following output&lt;/p&gt;

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

    Auto-merging Bob.txt
    CONFLICT (content): Merge conflict in Bob.txt
    Automatic merge failed; fix conflicts and then commit the result.


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

&lt;/div&gt;

&lt;p&gt;The same line has changed on both of the branches, and git can't handle this on it's own. &lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;git status&lt;/code&gt; you'll get all the usual helpful instructions on how to continue. &lt;/p&gt;

&lt;p&gt;First we have to resolve the conflict by hand. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For an easy conflict like this one your favorite text editor will do fine. For merging large files with lots of changes a more powerful tool will make your life much easier, and I'd assume your favorite IDE comes with version control tools and a nice view for merging. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you open &lt;code&gt;Bob.txt&lt;/code&gt; you'll see something similar to this (I've truncated whatever we might have put on the second line before): &lt;/p&gt;

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

    &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
    Hi! I'm Bob. I've been here for a while now.
    =======
    Hi! I'm Bobby. I'm new here.
    &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; bobby_branch
    [... whatever you've put on line 2]


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

&lt;/div&gt;

&lt;p&gt;On top you see what has changed in &lt;code&gt;Bob.txt&lt;/code&gt; on the current HEAD, below you see what has changed in the branch we're merging in.&lt;/p&gt;

&lt;p&gt;To resolve the conflict by hand, you'll just need to make sure that you end up with some reasonable content and without the special lines git has introduced to the file.&lt;/p&gt;

&lt;p&gt;So go ahead and change the file to something like this: &lt;/p&gt;

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

    Hi! I'm Bobby. I've been here for a while now.
    [...]


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

&lt;/div&gt;

&lt;p&gt;From here what we're doing is exactly what we'd do for any changes. &lt;br&gt;
We &lt;em&gt;stage&lt;/em&gt; them when we &lt;code&gt;add Bob.txt&lt;/code&gt;, and then we &lt;code&gt;commit&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We already know the commit for the changes we've made to resolve the conflict. It's the &lt;em&gt;merge commit&lt;/em&gt; that is always present when merging. &lt;/p&gt;

&lt;p&gt;Should you ever realize in the middle of resolving conflicts that you actually don't want to follow through with the &lt;code&gt;merge&lt;/code&gt;, you can just &lt;code&gt;abort&lt;/code&gt; it by running &lt;code&gt;git merge --abort&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Rebasing
&lt;/h2&gt;

&lt;p&gt;Git has another clean way to integrate changes between two branches, which is called &lt;code&gt;rebase&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We still recall that a branch is always based on another. When you create it, you &lt;em&gt;branch away&lt;/em&gt; from somewhere. &lt;/p&gt;

&lt;p&gt;In our simple merging example we branched from &lt;em&gt;master&lt;/em&gt; at a specific commit, then committed some changes on both &lt;em&gt;master&lt;/em&gt; and the &lt;code&gt;change_alice&lt;/code&gt; branch. &lt;/p&gt;

&lt;p&gt;When a branch is diverging from the one it's based on and you want to integrate the latest changes back into your current branch, &lt;code&gt;rebase&lt;/code&gt; offers a cleaner way of doing that than a &lt;code&gt;merge&lt;/code&gt; would. &lt;/p&gt;

&lt;p&gt;As we've seen, a &lt;code&gt;merge&lt;/code&gt; introduces a &lt;em&gt;merge commit&lt;/em&gt; in which the two histories get integrated again. &lt;/p&gt;

&lt;p&gt;Viewed simply, rebasing just changes the point in history (the commit) your branch is based on. &lt;/p&gt;

&lt;p&gt;To try that out, let's first checkout the &lt;em&gt;master&lt;/em&gt; branch again, then create/checkout a new branch based on it. &lt;br&gt;
I called mine &lt;code&gt;add_patrick&lt;/code&gt; and I added a new &lt;code&gt;Patrick.txt&lt;/code&gt; file and committed that with the message 'Add Patrick'. &lt;/p&gt;

&lt;p&gt;When you've added a commit to the branch, get back to &lt;em&gt;master&lt;/em&gt;, make a change and commit it. I added some more text to &lt;code&gt;Alice.txt&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Like in our merging example the history of these two branches diverges at a common ancestor as you can see in the diagram below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwvtlr5a8qx8tjitt4gjh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwvtlr5a8qx8tjitt4gjh.png" alt="History before a rebase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's &lt;code&gt;checkout add_patrick&lt;/code&gt; again, and get that change that was made on &lt;em&gt;master&lt;/em&gt; into the branch we work on! &lt;/p&gt;

&lt;p&gt;When we &lt;code&gt;git rebase master&lt;/code&gt;, we re-base our &lt;code&gt;add_patrick&lt;/code&gt; branch on the current state of the &lt;em&gt;master&lt;/em&gt; branch. &lt;/p&gt;

&lt;p&gt;The output of that command gives us a nice hint at what is happening in it: &lt;/p&gt;

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

    First, rewinding head to replay your work on top of it...
    Applying: Add Patrick


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

&lt;/div&gt;

&lt;p&gt;As we remember &lt;em&gt;HEAD&lt;/em&gt; is the pointer to the current commit we're at in our &lt;em&gt;Dev Environment&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;It's pointing to the same place as &lt;code&gt;add_patrick&lt;/code&gt; before the rebase starts. For the rebase, it then first moves back to the common ancestor, before moving to the current head of the branch we want to re-base ours on. &lt;/p&gt;

&lt;p&gt;So &lt;em&gt;HEAD&lt;/em&gt; moves from the &lt;em&gt;0cfc1d2&lt;/em&gt; commit, to the &lt;em&gt;7639f4b&lt;/em&gt; commit that is at the head of &lt;em&gt;master&lt;/em&gt;. &lt;br&gt;
Then rebase applies every single commit we made on our &lt;code&gt;add_patrick&lt;/code&gt; branch to that. &lt;/p&gt;

&lt;p&gt;To be more exact what &lt;em&gt;git&lt;/em&gt; does after moving &lt;em&gt;HEAD&lt;/em&gt; back to the common ancestor of the branches, is to store parts of every single commit you've made on the branch (the &lt;code&gt;diff&lt;/code&gt; of changes, and the commit text, author, etc.). &lt;/p&gt;

&lt;p&gt;After that it does a &lt;code&gt;checkout&lt;/code&gt; of the latest commit of the branch you're rebasing on, and then applies each of the stored changed &lt;strong&gt;as a new commit&lt;/strong&gt; on top of that.&lt;/p&gt;

&lt;p&gt;So in our original simplified view, we'd assume that after the &lt;code&gt;rebase&lt;/code&gt; the &lt;em&gt;0cfc1d2&lt;/em&gt; commit doesn't point to the common ancestor anymore in it's history, but points to the head of master. &lt;br&gt;
In fact the &lt;em&gt;0cfc1d2&lt;/em&gt; commit is gone, and the &lt;code&gt;add_patrick&lt;/code&gt; branch starts with a new &lt;em&gt;0ccaba8&lt;/em&gt; commit, that has the latest commit of &lt;em&gt;master&lt;/em&gt; as its ancestor. &lt;br&gt;
We made it look, like our &lt;code&gt;add_patrick&lt;/code&gt; was based on the current &lt;em&gt;master&lt;/em&gt; not an older version of it, but in doing so we re-wrote the history of the branch.&lt;br&gt;&lt;br&gt;
At the end of this tutorial we'll learn a bit more about re-writing history and when it's appropriate and inappropriate to do so. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fm6bk5b4gssxor8fin3up.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fm6bk5b4gssxor8fin3up.png" alt="History after rebase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Rebase&lt;/code&gt; is an incredibly powerful tool when you're working on your own development branch which is based on a shared branch, e.g. the &lt;em&gt;master&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Using rebase you can make sure that you frequently integrate the changes other people make and push to &lt;em&gt;master&lt;/em&gt;, while keeping a clean linear history that allows you to do a &lt;code&gt;fast-forward merge&lt;/code&gt; when it's time to get your work into the shared branch. &lt;/p&gt;

&lt;p&gt;Keeping a linear history also makes reading or looking at (try out &lt;code&gt;git log --graph&lt;/code&gt; or take a look at the branch view of &lt;em&gt;GitHub&lt;/em&gt; or &lt;em&gt;GitLab&lt;/em&gt;) commit logs much more useful than having a history littered with &lt;em&gt;merge commits&lt;/em&gt;, usually just using the default text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolving conflicts
&lt;/h3&gt;

&lt;p&gt;Just like for a &lt;code&gt;merge&lt;/code&gt; you may run into conflicts, if you run into two commits changing the same parts of a file. &lt;/p&gt;

&lt;p&gt;However when you encounter a conflict during a &lt;code&gt;rebase&lt;/code&gt; you don't fix it in an extra &lt;em&gt;merge commit&lt;/em&gt;, but can simply resolve it in the commit that is currently being applied. &lt;br&gt;
Again, basing your changes directly on the current state of the original branch. &lt;/p&gt;

&lt;p&gt;Actually resolving conflicts while you &lt;code&gt;rebase&lt;/code&gt; is very similar to how you would for a &lt;code&gt;merge&lt;/code&gt; so refer back to that section if you're not sure anymore how to do it. &lt;/p&gt;

&lt;p&gt;The only distinction is, that as you're not introducing a &lt;em&gt;merge commit&lt;/em&gt; there is no need to &lt;code&gt;commit&lt;/code&gt; your resolution. Simply &lt;code&gt;add&lt;/code&gt; the changes to the &lt;em&gt;Staging Environment&lt;/em&gt; and then &lt;code&gt;git rebase --continue&lt;/code&gt;. The conflict will be resolved in the commit that was just being applied. &lt;/p&gt;

&lt;p&gt;As when merging, you can always stop and drop everything you've done so far when you &lt;code&gt;git rebase --abort&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Updating the &lt;em&gt;Dev Environment&lt;/em&gt; with remote changes
&lt;/h2&gt;

&lt;p&gt;So far we've only learned how to make and share changes.&lt;/p&gt;

&lt;p&gt;That fits what you'll do if you're just working on your own, but usually there'll be a lot of people that do just the same, and we're gonna want to get their changes from the &lt;em&gt;Remote Repository&lt;/em&gt; into our &lt;em&gt;Dev Environment&lt;/em&gt; somehow.&lt;/p&gt;

&lt;p&gt;Because it has been a while, lets have another look at the components of git: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fc6ya4uoag4i6uyay138i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fc6ya4uoag4i6uyay138i.png" alt="git components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like your &lt;em&gt;Dev Environment&lt;/em&gt; everyone else working on the same source code has theirs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fg73azyk7at0p4impmh8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fg73azyk7at0p4impmh8b.png" alt="many dev environments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of these &lt;em&gt;Dev Environments&lt;/em&gt; have their own &lt;em&gt;working&lt;/em&gt; and &lt;em&gt;staged&lt;/em&gt; changes, that are at some point &lt;code&gt;committed&lt;/code&gt; to the &lt;em&gt;Local Repository&lt;/em&gt; and finally &lt;code&gt;pushed&lt;/code&gt; to the &lt;em&gt;Remote&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;For our example, we'll use the online tools offered by &lt;em&gt;GitHub&lt;/em&gt;, to simulate someone else making changes to the &lt;em&gt;remote&lt;/em&gt; while we work. &lt;/p&gt;

&lt;p&gt;Go to your &lt;code&gt;fork&lt;/code&gt; of this repo on &lt;a href="https://www.github.com" rel="noopener noreferrer"&gt;github.com&lt;/a&gt; and open the &lt;code&gt;Alice.txt&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;Find the edit button and make and commit a change via the website. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzkps04oj6azys64thk50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzkps04oj6azys64thk50.png" alt="github edit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this repository I have added a remote change to &lt;code&gt;Alice.txt&lt;/code&gt; on a branch called &lt;code&gt;fetching_changes_sample&lt;/code&gt;, but in your version of the repository you can of course just change the file on &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Fetching&lt;/em&gt; Changes
&lt;/h3&gt;

&lt;p&gt;We still remember that when you &lt;code&gt;git push&lt;/code&gt;, you synchronize changes made to the &lt;em&gt;Local Repository&lt;/em&gt; into the &lt;em&gt;Remote Repository&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;To get changes made to the &lt;em&gt;Remote&lt;/em&gt; into your &lt;em&gt;Local Repository&lt;/em&gt; you use &lt;code&gt;git fetch&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This gets any changes on the remote - so commits as well as branches - into your &lt;em&gt;Local Repository&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Note that at this point, changes aren't integrated into the local branches and thus the &lt;em&gt;Working Directory&lt;/em&gt; and &lt;em&gt;Staging Area&lt;/em&gt; yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fmf4jaimvkwgsw1xi3o6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fmf4jaimvkwgsw1xi3o6y.png" alt="Fetching changes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;git status&lt;/code&gt; now, you'll see another great example of git commands telling you exactly what is going on: &lt;/p&gt;

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

    git status
    On branch fetching_changes_sample
    Your branch is behind 'origin/fetching_changes_sample' by 1 commit, and can be fast-forwarded.
      (use "git pull" to update your local branch)


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;Pulling&lt;/em&gt; Changes
&lt;/h3&gt;

&lt;p&gt;As we have no &lt;em&gt;working&lt;/em&gt; or &lt;em&gt;staged&lt;/em&gt; changes, we could just execute &lt;code&gt;git pull&lt;/code&gt; now to get the changes from the &lt;em&gt;Repository&lt;/em&gt; all the way into our working area. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pulling will implicitly also &lt;code&gt;fetch&lt;/code&gt; the &lt;em&gt;Remote Repository&lt;/em&gt;, but sometimes it is a good idea to do a &lt;code&gt;fetch&lt;/code&gt; on it's own. &lt;br&gt;
For example when you want to synchronize any new &lt;em&gt;remote&lt;/em&gt; branches, or when you want to make sure your &lt;em&gt;Local Repository&lt;/em&gt; is up to date before you do a &lt;code&gt;git rebase&lt;/code&gt; on something like &lt;code&gt;origin/master&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnacuifof8g4zxz5wzkri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnacuifof8g4zxz5wzkri.png" alt="Pulling in changes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we &lt;code&gt;pull&lt;/code&gt;, lets change a file locally to see what happens. &lt;/p&gt;

&lt;p&gt;Lets also change &lt;code&gt;Alice.txt&lt;/code&gt; in our &lt;em&gt;Working Directory&lt;/em&gt; now! &lt;/p&gt;

&lt;p&gt;If you now try to do a &lt;code&gt;git pull&lt;/code&gt; you'll see the following error: &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    git pull
    Updating df3ad1d..418e6f0
    error: Your local changes to the following files would be overwritten by merge:
            Alice.txt
    Please commit your changes or stash them before you merge.
    Aborting


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

&lt;/div&gt;

&lt;p&gt;You can not &lt;code&gt;pull&lt;/code&gt; in any changes, while there are modifications to files in the &lt;em&gt;Working Directory&lt;/em&gt; that are also changed by the commits you're &lt;code&gt;pull&lt;/code&gt;ing in. &lt;/p&gt;

&lt;p&gt;While one way around this is, to just get your changes to a point where you're confident in them, &lt;code&gt;add&lt;/code&gt; them to the &lt;em&gt;Staging Environment&lt;/em&gt;, before you finally &lt;code&gt;commit&lt;/code&gt; them, this is a good moment to learn about another great tool, the &lt;code&gt;git stash&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Stashing changes
&lt;/h3&gt;

&lt;p&gt;If at any point you have local changes that you do not yet want to put into a commit, or want to store somewhere while you try some different angle to solve a problem, you can &lt;code&gt;stash&lt;/code&gt; those changes away. &lt;/p&gt;

&lt;p&gt;A &lt;code&gt;git stash&lt;/code&gt; is basically a stack of changes on which you store any changes to the &lt;em&gt;Working Directory&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The commands you'll mostly use are &lt;code&gt;git stash&lt;/code&gt; which places any modifications to the &lt;em&gt;Working Directory&lt;/em&gt; on the stash, and &lt;code&gt;git stash pop&lt;/code&gt; which takes the latest change that was stashed and applies it the to the &lt;em&gt;Working Directory&lt;/em&gt; again. &lt;/p&gt;

&lt;p&gt;Just like the stack commands it's named after &lt;code&gt;git stash pop&lt;/code&gt; removes the latest stashed change before applying it again. &lt;br&gt;
If you want to keep the stashed changes, you can use &lt;code&gt;git stash apply&lt;/code&gt;, which doesn't remove them from the stash before applying them. &lt;/p&gt;

&lt;p&gt;To inspect you current &lt;code&gt;stash&lt;/code&gt; you can use &lt;code&gt;git stash list&lt;/code&gt; to list the individual entries, and &lt;code&gt;git stash show&lt;/code&gt; to show the changes in the latest entry on the &lt;code&gt;stash&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another nice convenience command is &lt;code&gt;git stash branch {BRANCH NAME}&lt;/code&gt;, which creates a branch, starting from the HEAD at the moment you've stashed the changes, and applies the stashed changes to that branch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that we know about &lt;code&gt;git stash&lt;/code&gt;, lets run it to remove our local changes to &lt;code&gt;Alice.txt&lt;/code&gt; from the &lt;em&gt;Working Directory&lt;/em&gt;, so that we can go ahead and &lt;code&gt;git pull&lt;/code&gt; the changes we've made via the website. &lt;/p&gt;

&lt;p&gt;After that, let's &lt;code&gt;git stash pop&lt;/code&gt; to get the changes back. &lt;br&gt;
As both the commit we &lt;code&gt;pull&lt;/code&gt;ed in and the &lt;code&gt;stash&lt;/code&gt;ed change modified &lt;code&gt;Alice.txt&lt;/code&gt; you wil have to resolve the conflict, just how you would in a  &lt;code&gt;merge&lt;/code&gt; or &lt;code&gt;rebase&lt;/code&gt;.&lt;br&gt;
When you're done &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;commit&lt;/code&gt; the change. &lt;/p&gt;

&lt;h3&gt;
  
  
  Pulling with Conflicts
&lt;/h3&gt;

&lt;p&gt;Now that we've understood how to &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;pull&lt;/code&gt; &lt;em&gt;Remote Changes&lt;/em&gt; into our &lt;em&gt;Dev Environment&lt;/em&gt;, it's time to create some conflicts! &lt;/p&gt;

&lt;p&gt;Do not &lt;code&gt;push&lt;/code&gt; the commit that changed &lt;code&gt;Alice.txt&lt;/code&gt; and head back to your &lt;em&gt;Remote Repository&lt;/em&gt; on &lt;a href="https://www.github.com" rel="noopener noreferrer"&gt;github.com&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;There we're also again going to change &lt;code&gt;Alice.txt&lt;/code&gt; and commit the change. &lt;/p&gt;

&lt;p&gt;Now there's actually two conflicts between our &lt;em&gt;Local&lt;/em&gt; and &lt;em&gt;Remote Repositories&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Don't forget to run &lt;code&gt;git fetch&lt;/code&gt; to see the remote change without &lt;code&gt;pull&lt;/code&gt;ing it in right away. &lt;/p&gt;

&lt;p&gt;If you now run &lt;code&gt;git status&lt;/code&gt; you will see, that both branches have one commit on them that differs from the other. &lt;/p&gt;

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

    git status
    On branch fetching_changes_sample
    Your branch and 'origin/fetching_changes_sample' have diverged,
    and have 1 and 1 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)


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

&lt;/div&gt;

&lt;p&gt;In addition we've changed the same file in both of those commits, to introduce a &lt;code&gt;merge&lt;/code&gt; conflict we'll have to resolve. &lt;/p&gt;

&lt;p&gt;When you &lt;code&gt;git pull&lt;/code&gt; while there is a difference between the &lt;em&gt;Local&lt;/em&gt; and &lt;em&gt;Remote Repository&lt;/em&gt; the exact same thing happens as when you &lt;code&gt;merge&lt;/code&gt; two branches. &lt;/p&gt;

&lt;p&gt;Additionally, you can think of the relationship between branches on the &lt;em&gt;Remote&lt;/em&gt; and the one in the &lt;em&gt;Local Repository&lt;/em&gt; as a special case of creating a branch based on another. &lt;br&gt;
A local branch is based on a branches state on the &lt;em&gt;Remote&lt;/em&gt; from the time you last &lt;code&gt;fetched&lt;/code&gt; it. &lt;/p&gt;

&lt;p&gt;Thinking that way, the two options you have to get &lt;em&gt;remote&lt;/em&gt; changes make a lot of sense: &lt;/p&gt;

&lt;p&gt;When you &lt;code&gt;git pull&lt;/code&gt; the &lt;em&gt;Local&lt;/em&gt; and &lt;em&gt;Remote&lt;/em&gt; version of a branch will be &lt;code&gt;merged&lt;/code&gt;. Just like &lt;code&gt;merging&lt;/code&gt; branches, this will introduce a _merge commit. &lt;/p&gt;

&lt;p&gt;As any &lt;em&gt;local&lt;/em&gt; branch is based on it's respective &lt;em&gt;remote&lt;/em&gt; version, we can also &lt;code&gt;rebase&lt;/code&gt; it, so that any changes we may have made locally, appear as if they were based on the latest version that is available in the _Remote Repository. &lt;br&gt;
To do that, we can use &lt;code&gt;git pull --rebase&lt;/code&gt; (or the shorthand &lt;code&gt;git pull -r&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;As detailed in the section on Rebasing, there is a benefit in keeping a clean linear history, which is why I would strongly recommend that whenever you &lt;code&gt;git pull&lt;/code&gt; you do a &lt;code&gt;git pull -r&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can also tell git to use &lt;code&gt;rebase&lt;/code&gt; instead of &lt;code&gt;merge&lt;/code&gt; as it's default strategy when your &lt;code&gt;git pull&lt;/code&gt;, by setting the &lt;code&gt;pull.rebase&lt;/code&gt; flag with a command like this &lt;code&gt;git config --global pull.rebase true&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you haven't already run &lt;code&gt;git pull&lt;/code&gt; when I first mentioned it a few paragraphs ago, let's now run &lt;code&gt;git pull -r&lt;/code&gt; to get the remote changes while making it look like our new commit just happened after them. &lt;/p&gt;

&lt;p&gt;Of course like with a normal &lt;code&gt;rebase&lt;/code&gt; (or &lt;code&gt;merge&lt;/code&gt;) you'll have to resolve the conflict we introduced for the &lt;code&gt;git pull&lt;/code&gt; to be done. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cherry-picking
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Congratulations! You've made it to the more advanced features! &lt;/p&gt;

&lt;p&gt;By now you understand how to use all the typical git commands and more importantly how they work. &lt;/p&gt;

&lt;p&gt;This will hopefully make the following concepts much simpler to understand than if I just told you what commands to type in. &lt;/p&gt;

&lt;p&gt;So let's head right in an learn how to &lt;code&gt;cherry-pick&lt;/code&gt; commits!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From earlier sections you still remember roughly what a &lt;code&gt;commit&lt;/code&gt; is made off, right? &lt;/p&gt;

&lt;p&gt;And how when you &lt;code&gt;rebase&lt;/code&gt; a branch your commits are applied as new commits with the same &lt;em&gt;change set&lt;/em&gt; and &lt;em&gt;message&lt;/em&gt;? &lt;/p&gt;

&lt;p&gt;Whenever you want to just take a few choice changes from one branch and apply them to another branch, you want to &lt;code&gt;cherry-pick&lt;/code&gt; these commits and put them on your branch. &lt;/p&gt;

&lt;p&gt;That is exactly what &lt;code&gt;git cherry-pick&lt;/code&gt; allows you to do with either single commits or a range of commits. &lt;/p&gt;

&lt;p&gt;Just like during a &lt;code&gt;rebase&lt;/code&gt; this will actually put the changes from these commits into a new commit on your current branch. &lt;/p&gt;

&lt;p&gt;Lets have a look at an example each for &lt;code&gt;cherry-pick&lt;/code&gt;ing one or more commits: &lt;/p&gt;

&lt;p&gt;The figure below shows three branches before we have done anything. Let's assume we really want to get some changes from the &lt;code&gt;add_patrick&lt;/code&gt; branch into the &lt;code&gt;change_alice&lt;/code&gt; branch. Sadly they haven't made it into master yet, so we can't just &lt;code&gt;rebase&lt;/code&gt; onto master to get those changes (along with any other changes on the other branch, that we might not even want). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fb0pqh8xb50fv2c6in7hi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fb0pqh8xb50fv2c6in7hi.png" alt="Branches before cherry-picking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let's just &lt;code&gt;git cherry-pick&lt;/code&gt; the commit &lt;em&gt;63fc421&lt;/em&gt;. &lt;br&gt;
The figure below visualizes what happens when we run &lt;code&gt;git cherry-pick 63fc421&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fao5acwjnk68g153u2aic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fao5acwjnk68g153u2aic.png" alt="Cherry-picking a single commit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, a new commit with the changes we wanted shows up on branch. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At this point note that like with any other kind of getting changes onto a branch that we've seen before, any conflicts that arise during a &lt;code&gt;cherry-pick&lt;/code&gt; will have to be &lt;em&gt;resolved&lt;/em&gt; by us, before the command can go through. &lt;/p&gt;

&lt;p&gt;Also like all other commands you can either &lt;code&gt;--continue&lt;/code&gt; a &lt;code&gt;cherry-pick&lt;/code&gt; when you've resolved conflicts, or decide to &lt;code&gt;--abort&lt;/code&gt; the command entirely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The figure below visualizes &lt;code&gt;cherry-pick&lt;/code&gt;ing a range of commits instead of a single one. You can simply do that by calling the command in the form &lt;code&gt;git cherry-pick &amp;lt;from&amp;gt;..&amp;lt;to&amp;gt;&lt;/code&gt; or in our example below as &lt;code&gt;git cherry-pick 0cfc1d2..41fbfa7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fqccfaygtbybvxknopfon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fqccfaygtbybvxknopfon.png" alt="Cherry-picking commit range"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Rewriting history
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm repeating myself now, but you still remember &lt;code&gt;rebase&lt;/code&gt; well enough right? Else quickly jump back to that section, before continuing here, as we'll use what we already know when learning about how change history!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you know a &lt;code&gt;commit&lt;/code&gt; basically contains your changes, a message and few other things. &lt;/p&gt;

&lt;p&gt;The 'history' of a branch is made up of all it's commits. &lt;/p&gt;

&lt;p&gt;But lets say you've just made a &lt;code&gt;commit&lt;/code&gt; and then notice, that you've forgotten to add a file, or you made a typo and the change leaves you with broken code. &lt;/p&gt;

&lt;p&gt;We'll briefly look at two things we could do to fix that, and make it look like it never happened. &lt;/p&gt;

&lt;p&gt;Let's switch to a new branch with &lt;code&gt;git checkout -b rewrite_history&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now make some changes to both &lt;code&gt;Alice.txt&lt;/code&gt; and &lt;code&gt;Bob.txt&lt;/code&gt;, and then &lt;code&gt;git add Alice.txt&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;git commit&lt;/code&gt; using a message like "This is history" and you're done. &lt;/p&gt;

&lt;p&gt;Wait, did I say we're done? No, you'll clearly see that we've made some mistakes here: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We forgot to add the changes to &lt;code&gt;Bob.txt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We didn't write a &lt;a href="https://chris.beams.io/posts/git-commit/" rel="noopener noreferrer"&gt;good commit message&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Amending the last Commit
&lt;/h3&gt;

&lt;p&gt;One way to fix both of these in one go would be to &lt;code&gt;amend&lt;/code&gt; the commit we've just made. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Amend&lt;/code&gt;ing the latest commit basically works just like making a new one. &lt;/p&gt;

&lt;p&gt;Before we do anything take a look at your latest commit, with &lt;code&gt;git show {COMMIT}&lt;/code&gt;. Put either the commit hash (which you'll probably still see in your command line from the &lt;code&gt;git commit&lt;/code&gt; call, or in the &lt;code&gt;git log&lt;/code&gt;), or just &lt;em&gt;HEAD&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Just like in the &lt;code&gt;git log&lt;/code&gt; you'll see the message, author, date and of course changes. &lt;/p&gt;

&lt;p&gt;Now let's &lt;code&gt;amend&lt;/code&gt; what we've done in that commit. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;git add Bob.txt&lt;/code&gt; to get the changes to the &lt;em&gt;Staging Area&lt;/em&gt;, and then &lt;code&gt;git commit --amend&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;What happens next is your latest commit being unrolled, the new changes from the &lt;em&gt;Staging Area&lt;/em&gt; added to the existing one, and the editor for the commit message opening. &lt;/p&gt;

&lt;p&gt;In the editor you'll see the previous commit message. &lt;br&gt;
Feel free to change it to something better. &lt;/p&gt;

&lt;p&gt;After you're done, take another look at the latest commit with &lt;code&gt;git show HEAD&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As you've certainly expected by now, the commit hash is different. The original commit is gone, and in it's place there is a new one, with the combined changes and new commit message. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note how the other commit data like author and date are unchanged from the original commit. You can mess with those too, if you really want, by using the extra &lt;code&gt;--author={AUTHOR}&lt;/code&gt; and &lt;code&gt;--date={DATE}&lt;/code&gt; flags when amending. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Congratulations! You've just successfully re-written history for the first time! &lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Rebase
&lt;/h3&gt;

&lt;p&gt;Generally when we &lt;code&gt;git rebase&lt;/code&gt;, we &lt;code&gt;rebase&lt;/code&gt; onto a branch. When we do something like &lt;code&gt;git rebase origin/master&lt;/code&gt;, what actually happens, is a rebase onto the &lt;em&gt;HEAD&lt;/em&gt; of that branch. &lt;/p&gt;

&lt;p&gt;In fact if we felt like it, we could &lt;code&gt;rebase&lt;/code&gt; onto any commit. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember that a commit contains information about the history that came before it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Like many other commands &lt;code&gt;git rebase&lt;/code&gt; has an &lt;em&gt;interactive&lt;/em&gt; mode. &lt;/p&gt;

&lt;p&gt;Unlike most others, the &lt;em&gt;interactive&lt;/em&gt; &lt;code&gt;rebase&lt;/code&gt; is something you'll probably be using a lot, as it allows you to change history as much as you want. &lt;/p&gt;

&lt;p&gt;Especially if you follow a work-flow of making many small commits of your changes, which allow you to easily jump back if you made a mistake, &lt;em&gt;interactive&lt;/em&gt; &lt;code&gt;rebase&lt;/code&gt; will be your closest ally. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enough talk! Lets do something!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Switch back to your &lt;em&gt;master&lt;/em&gt; branch and &lt;code&gt;git checkout&lt;/code&gt; a new branch to work on. &lt;/p&gt;

&lt;p&gt;As before, we'll make some changes to both &lt;code&gt;Alice.txt&lt;/code&gt; and &lt;code&gt;Bob.txt&lt;/code&gt;, and then &lt;code&gt;git add Alice.txt&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then we &lt;code&gt;git commit&lt;/code&gt; using a message like "Add text to Alice". &lt;/p&gt;

&lt;p&gt;Now instead of changing that commit, we'll &lt;code&gt;git add Bob.txt&lt;/code&gt; and &lt;code&gt;git commit&lt;/code&gt; that change as well. As message I used "Add Bob.txt". &lt;/p&gt;

&lt;p&gt;And to make things more interesting, we'll make another change to &lt;code&gt;Alice.txt&lt;/code&gt; which we'll &lt;code&gt;git add&lt;/code&gt; and &lt;code&gt;git commit&lt;/code&gt;. As a message I used "Add more text to Alice". &lt;/p&gt;

&lt;p&gt;If we now have a look at the branch's history with &lt;code&gt;git log&lt;/code&gt; (or for just a quick look preferably with &lt;code&gt;git log --oneline&lt;/code&gt;), we'll see our three commits on top of whatever was on your &lt;em&gt;master&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;For me it looks like this: &lt;/p&gt;

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

git log --oneline
0b22064 (HEAD -&amp;gt; interactiveRebase) Add more text to Alice
062ef13 Add Bob.txt
9e06fca Add text to Alice
df3ad1d (origin/master, origin/HEAD, master) Add Alice
800a947 Add Tutorial Text


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

&lt;/div&gt;

&lt;p&gt;There's two things we'd like to fix about this, which for the sake of learning different things, will be a bit different than in the previous section on &lt;code&gt;amend&lt;/code&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put both changes to &lt;code&gt;Alice.txt&lt;/code&gt; in a single commit&lt;/li&gt;
&lt;li&gt;Consistently name things, and remove the &lt;em&gt;.txt&lt;/em&gt; from the message about &lt;code&gt;Bob.txt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To change the three new commits, we'll want to rebase onto the commit just before them. That commit for me is &lt;code&gt;df3ad1d&lt;/code&gt;, but we can also reference it as the third commit from the current &lt;em&gt;HEAD&lt;/em&gt; as &lt;code&gt;HEAD~3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To start an &lt;em&gt;interactive&lt;/em&gt; &lt;code&gt;rebase&lt;/code&gt; we use &lt;code&gt;git rebase -i {COMMIT}&lt;/code&gt;, so let's run &lt;code&gt;git rebase -i HEAD~3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What you'll see is your editor of choice showing something like this: &lt;/p&gt;

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

    pick 9e06fca Add text to Alice
    pick 062ef13 Add Bob.txt
    pick 0b22064 Add more text to Alice
    # Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    #
    # These lines can be re-ordered; they are executed from top to bottom.
    #
    # If you remove a line here THAT COMMIT WILL BE LOST.
    #
    # However, if you remove everything, the rebase will be aborted.
    #
    # Note that empty commits are commented out


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

&lt;/div&gt;

&lt;p&gt;Note as always how &lt;code&gt;git&lt;/code&gt; explains everything you can do right there when you call the command. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Commands&lt;/em&gt; you'll probably be using most are &lt;code&gt;reword&lt;/code&gt;, &lt;code&gt;squash&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;. (And &lt;code&gt;pick&lt;/code&gt; but that one's there by default)&lt;/p&gt;

&lt;p&gt;Take a moment to think about what you see and what we're going to use to achieve our two goals from above. I'll wait. &lt;/p&gt;

&lt;p&gt;Got a plan? Perfect!&lt;/p&gt;

&lt;p&gt;Before we start making changes, take note of the fact, that the commits are listed from oldest to newest, and thus in the opposite direction of the &lt;code&gt;git log&lt;/code&gt; output. &lt;/p&gt;

&lt;p&gt;I'll start off with the easy change and make it so we get to change the commit message of the middle commit. &lt;/p&gt;

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

    pick 9e06fca Add text to Alice
    reword 062ef13 Add Bob.txt
    pick 0b22064 Add more text to Alice
    # Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)
    [...]


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

&lt;/div&gt;

&lt;p&gt;Now to getting the two changes of &lt;code&gt;Alice.txt&lt;/code&gt; into one commit. &lt;/p&gt;

&lt;p&gt;Obviously what we want to do is to &lt;code&gt;squash&lt;/code&gt; the later of the two into the first one, so let's put that command in place of the &lt;code&gt;pick&lt;/code&gt; on the second commit changing &lt;code&gt;Alice.txt&lt;/code&gt;. For me in the example that's &lt;em&gt;0b22064&lt;/em&gt;.&lt;/p&gt;

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

    pick 9e06fca Add text to Alice
    reword 062ef13 Add Bob.txt
    squash 0b22064 Add more text to Alice
    # Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)
    [...]


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

&lt;/div&gt;

&lt;p&gt;Are we done? Will that do what we want? &lt;/p&gt;

&lt;p&gt;It wont right? As the comments in the file tell us: &lt;/p&gt;

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

    # s, squash = use commit, but meld into previous commit


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

&lt;/div&gt;

&lt;p&gt;So what we've done so far, will merge the changes of the second Alice commit, with the Bob commit. That's not what we want. &lt;/p&gt;

&lt;p&gt;Another powerful thing we can do in an &lt;em&gt;interactive&lt;/em&gt; &lt;code&gt;rebase&lt;/code&gt; is changing the order of commits. &lt;/p&gt;

&lt;p&gt;If you've read what the comments told you carefully, you already know how: Simply move the lines!&lt;/p&gt;

&lt;p&gt;Thankfully you're in your favorite text editor, so go ahead and move the second Alice commit after the first.&lt;/p&gt;

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

    pick 9e06fca Add text to Alice
    squash 0b22064 Add more text to Alice
    reword 062ef13 Add Bob.txt
    # Rebase df3ad1d..0b22064 onto df3ad1d (3 commands)
    [...]


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

&lt;/div&gt;

&lt;p&gt;That should do the trick, so close the editor to tell &lt;code&gt;git&lt;/code&gt; to start executing the commands. &lt;/p&gt;

&lt;p&gt;What happens next is just like a normal &lt;code&gt;rebase&lt;/code&gt;: starting with the commit you've referenced when starting it, each of the commits you have listed will be applied one after the other. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Right now it won't happen, but when you re-order actual code changes, it may happen, that you run into conflicts during the &lt;code&gt;rebase&lt;/code&gt;. After all you've possibly mixed up changes that were building on each other. &lt;/p&gt;

&lt;p&gt;Just resolve them, as you would usually. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After applying the first commit, the editor will open and allow you to put a new message for the commit combining the changes to &lt;code&gt;Alice.txt&lt;/code&gt;. I've thrown away the text of both commits and put "Add a lot of very important text to Alice". &lt;/p&gt;

&lt;p&gt;After you close the editor to finish that commit, it will open again to allow you to change the message of the &lt;code&gt;Add Bob.txt&lt;/code&gt; commit. Remove the ".txt" and continue by closing the editor. &lt;/p&gt;

&lt;p&gt;That's it! You've rewritten history again. This time a lot more substantially than when &lt;code&gt;amend&lt;/code&gt;ing!&lt;/p&gt;

&lt;p&gt;If you look at the &lt;code&gt;git log&lt;/code&gt; again, you'll see that there's two new commits in place of the three that we had previously. But by now you're used to what &lt;code&gt;rebase&lt;/code&gt; does to commits and have expected that. &lt;/p&gt;

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

git log --oneline
105177b (HEAD -&amp;gt; interactiveRebase) Add Bob
ed78fa1 Add a lot very important text to Alice
df3ad1d (origin/master, origin/HEAD, master) Add Alice
800a947 Add Tutorial Text


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

&lt;/div&gt;

&lt;h3&gt;
  
  
  Public History, why you shouldn't rewrite it, and how to still do it safely
&lt;/h3&gt;

&lt;p&gt;As noted before, changing history is a incredibly useful part of any work-flow that involves making a lot of small commits while you work. &lt;/p&gt;

&lt;p&gt;While all the small atomic changes make it very easy for you to e.g. verify that with each change your test-suite still passes and if it doesn't, remove or amend just these specific changes, the 100 commits you've made to write &lt;code&gt;HelloWorld.java&lt;/code&gt; are probably not something you want to share with people. &lt;/p&gt;

&lt;p&gt;Most likely what you want to share with them, are a few well formed changes with nice commit messages telling your colleagues what you did for which reason. &lt;/p&gt;

&lt;p&gt;As long as all those small commits only exist in your &lt;em&gt;Dev Environment&lt;/em&gt;, you're perfectly save to do a &lt;code&gt;git rebase -i&lt;/code&gt; and change history to your hearts content. &lt;/p&gt;

&lt;p&gt;Things get problematic when it comes to changing &lt;em&gt;Public History&lt;/em&gt;. That means anything that has already made it to the &lt;em&gt;Remote Repository&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At this point is has become &lt;em&gt;public&lt;/em&gt; and other people's branches might be based on that history. That really makes it something you generally don't want to mess with. &lt;/p&gt;

&lt;p&gt;The usual advice is to "Never rewrite public history!" and while I repeat that here, I've got to admit, that there is a decent amount of cases in which you might still want to rewrite &lt;em&gt;public history&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;In all of theses cases that history isn't 'really' &lt;em&gt;public&lt;/em&gt; though. You most certainly don't want to go rewriting history on the &lt;em&gt;master&lt;/em&gt; branch of an open source project, or something like your company's &lt;em&gt;release&lt;/em&gt; branch. &lt;/p&gt;

&lt;p&gt;Where you might want to rewrite history are branches that you've &lt;code&gt;push&lt;/code&gt;ed just to share with some colleagues. &lt;/p&gt;

&lt;p&gt;You might be doing trunk-based development, but want to share something that doesn't even compile yet, so you obviously don't want to put that on the main branch knowingly. &lt;br&gt;
Or you might have a work-flow in which you share feature branches. &lt;/p&gt;

&lt;p&gt;Especially with feature branches you hopefully &lt;code&gt;rebase&lt;/code&gt; them onto the current &lt;em&gt;master&lt;/em&gt; frequently. But as we know, a &lt;code&gt;git rebase&lt;/code&gt; adds our branch's commits as &lt;em&gt;new&lt;/em&gt; commits on top of the thing we're basing them on. This rewrites history. And in the case of a shared feature branch it rewrites &lt;em&gt;public history&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;So what should we do if we follow the "Never rewrite public history" mantra? &lt;/p&gt;

&lt;p&gt;Never rebase our branch and hope it still merges into &lt;em&gt;master&lt;/em&gt; in the end? &lt;/p&gt;

&lt;p&gt;Not use shared feature branches? &lt;/p&gt;

&lt;p&gt;Admittedly that second one is actually a reasonable answer, but you might still not be able to do that. So the only thing you can do, is to accept rewriting the &lt;em&gt;public history&lt;/em&gt; and  &lt;code&gt;push&lt;/code&gt; the changed history to the &lt;em&gt;Remote Repository&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;If you just do a &lt;code&gt;git push&lt;/code&gt; you'll be notified that you're not allowed to do that, as your &lt;em&gt;local&lt;/em&gt; branch has diverged from the &lt;em&gt;remote&lt;/em&gt; one. &lt;/p&gt;

&lt;p&gt;You will need to &lt;code&gt;force&lt;/code&gt; pushing the changes, and overwrite the remote with your local version. &lt;/p&gt;

&lt;p&gt;As I've highlighted that so suggestively, you're probably ready to try &lt;code&gt;git push --force&lt;/code&gt; right now. You really shouldn't do that if you want to rewrite &lt;em&gt;public history&lt;/em&gt; safely though!&lt;/p&gt;

&lt;p&gt;You're much better off using &lt;code&gt;--force&lt;/code&gt;'s more careful sibling &lt;code&gt;--force-with-lease&lt;/code&gt; ! &lt;/p&gt;

&lt;p&gt;&lt;code&gt;--force-with-lease&lt;/code&gt; will check if your &lt;em&gt;local&lt;/em&gt; version of the &lt;em&gt;remote&lt;/em&gt; branch and the actual &lt;em&gt;remote&lt;/em&gt; match, before &lt;code&gt;push&lt;/code&gt;ing. &lt;/p&gt;

&lt;p&gt;By that you can ensure that you don't accidentally wipe any changes someone else may have &lt;code&gt;push&lt;/code&gt;ed while you where rewriting history!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1oqrvf1rx7ty8qwqs534.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1oqrvf1rx7ty8qwqs534.png" alt="What happens in a push --force-with-lease"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And on that note I'll leave you with a slightly changed mantra: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't rewrite public history unless you're really sure about what you're doing. And if you do, be safe and force-with-lease.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading history
&lt;/h2&gt;

&lt;p&gt;Knowing about the differences between the areas in your &lt;em&gt;Dev Environment&lt;/em&gt; - especially the &lt;em&gt;Local Repository&lt;/em&gt; - and how commits and the history work, doing a &lt;code&gt;rebase&lt;/code&gt; should not be scary to you. &lt;/p&gt;

&lt;p&gt;Still sometimes things go wrong. You may have done a &lt;code&gt;rebase&lt;/code&gt; and accidentally accepted the wrong version of file when resolving a conflict. &lt;/p&gt;

&lt;p&gt;Now instead of the feature you've added, there's just your colleagues added line of logging in a file. &lt;/p&gt;

&lt;p&gt;Luckily &lt;code&gt;git&lt;/code&gt; has your back, by having a built in safety feature called the &lt;em&gt;Reference Logs&lt;/em&gt; AKA &lt;code&gt;reflog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Whenever any &lt;em&gt;reference&lt;/em&gt; like the tip of a branch is updated in your &lt;em&gt;Local Repository&lt;/em&gt; a &lt;em&gt;Reference Log&lt;/em&gt; entry is added. &lt;/p&gt;

&lt;p&gt;So theres a record of any time you make a &lt;code&gt;commit&lt;/code&gt;, but also of when you &lt;code&gt;reset&lt;/code&gt; or otherwise move the &lt;code&gt;HEAD&lt;/code&gt; etc. &lt;/p&gt;

&lt;p&gt;Having read this tutorial so far, you see how this might come in handy when we've messed up a &lt;code&gt;rebase&lt;/code&gt; right? &lt;/p&gt;

&lt;p&gt;We know that a &lt;code&gt;rebase&lt;/code&gt; moves the &lt;code&gt;HEAD&lt;/code&gt; of our branch to the point we're basing it on and the applies our changes. An interactive &lt;code&gt;rebase&lt;/code&gt; works similarly, but might do things to those commits like &lt;em&gt;squashing&lt;/em&gt; or &lt;em&gt;rewording&lt;/em&gt; them. &lt;/p&gt;

&lt;p&gt;If you're not still on the branch on which we practiced interactive rebase, switch to it again, as we're about to practice some more there. &lt;/p&gt;

&lt;p&gt;Lets have a look at the &lt;code&gt;reflog&lt;/code&gt; of the things we've done on that branch by - you've guessed it - running &lt;code&gt;git reflog&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You'll probably see a lot of output, but the first few lines on the top should be similar to this: &lt;/p&gt;

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

git reflog
105177b (HEAD -&amp;gt; interactiveRebase) HEAD@{0}: rebase -i (finish): returning to refs/heads/interactiveRebase
105177b (HEAD -&amp;gt; interactiveRebase) HEAD@{1}: rebase -i (reword): Add Bob
ed78fa1 HEAD@{2}: rebase -i (squash): Add a lot very important text to Alice
9e06fca HEAD@{3}: rebase -i (start): checkout HEAD~3
0b22064 HEAD@{4}: commit: Add more text to Alice
062ef13 HEAD@{5}: commit: Add Bob.txt
9e06fca HEAD@{6}: commit: Add text to Alice
df3ad1d (origin/master, origin/HEAD, master) HEAD@{7}: checkout: moving from master to interactiveRebase


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

&lt;/div&gt;

&lt;p&gt;There it is. Every single thing we've done, from switching to the branch to doing the &lt;code&gt;rebase&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Quite cool to see the things we've done, but useless on it's own if we messed up somewhere, if it wasn't for the references at the start of each line. &lt;/p&gt;

&lt;p&gt;If you compare the &lt;code&gt;reflog&lt;/code&gt; output to when we looked at the &lt;code&gt;log&lt;/code&gt; the last time, you'll see those points relate to commit references, and we can use them just like that. &lt;/p&gt;

&lt;p&gt;Let's say we actually didn't want to do the rebase. How do we get rid of the changes it made? &lt;/p&gt;

&lt;p&gt;We move &lt;code&gt;HEAD&lt;/code&gt; to the point before the &lt;code&gt;rebase&lt;/code&gt; started with a &lt;code&gt;git reset 0b22064&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;0b22064&lt;/code&gt; is the commit before the &lt;code&gt;rebase&lt;/code&gt; in my case. More generally you can also reference it as &lt;em&gt;HEAD four changes ago&lt;/em&gt; via &lt;code&gt;HEAD@{4}&lt;/code&gt;. Note that should you have switched branches in between or done any other thing that creates a log entry, you might have a higher number there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you take a look at the &lt;code&gt;log&lt;/code&gt; now, you'll see the original state with three individual commits restored. &lt;/p&gt;

&lt;p&gt;But let's say we now realize that's not what we wanted. The &lt;code&gt;rebase&lt;/code&gt; is fine, we just don't like how we changed the message of the Bob commit. &lt;/p&gt;

&lt;p&gt;We could just do another &lt;code&gt;rebase -i&lt;/code&gt; in the current state, just like we did originally. &lt;/p&gt;

&lt;p&gt;Or we use the reflog and jump back to after the rebase and &lt;code&gt;amend&lt;/code&gt; the commit from there. &lt;/p&gt;

&lt;p&gt;But by now you know how to do either of that, so I'll let you try that on your own. And in addition you also know that there's the &lt;code&gt;reflog&lt;/code&gt; allowing you to undo most things you might end up doing by mistake. &lt;/p&gt;

</description>
      <category>git</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
