<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>MVHS |</title><link>https://kurse.richter.consulting/tags/mvhs/</link><atom:link href="https://kurse.richter.consulting/tags/mvhs/index.xml" rel="self" type="application/rss+xml"/><description>MVHS</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>de</language><lastBuildDate>Tue, 02 Jun 2026 07:00:00 +0100</lastBuildDate><image><url>https://kurse.richter.consulting/media/logo.svg</url><title>MVHS</title><link>https://kurse.richter.consulting/tags/mvhs/</link></image><item><title>Installation von Docker Desktop</title><link>https://kurse.richter.consulting/courses/container/install/</link><pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/install/</guid><description>&lt;p&gt;Die Firma Docker Inc. liefert für Entwickler ein einfaches Tool, um mit Containern starten zu können. Für die private Nutzung (und kleine Firmen) ist das Tool komplett kostenlos.&lt;/p&gt;
&lt;h2 id="docker-desktop-installieren"&gt;Docker Desktop installieren&lt;/h2&gt;
&lt;p&gt;Laden Sie die Installationsdatei von der offiziellen Seite herunter (Windows / macOS) oder installieren Sie diese über den Paket-Manager Ihrer Wahl.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/&gt;&lt;/svg&gt;
&lt;/span&gt; Download:
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path d="M39.676 32.972c-4.6 0-8.45 3.142-9.603 7.39c-4.063.571-7.218 4.031-7.218 8.246c0 4.1 2.954 7.523 6.84 8.293l.018.002a47 47 0 0 1 4.273.993L34 57.9c5.603 1.511 16.502 3.582 28.568 3.279c.77 1.573 1.95 2.907 3.441 3.809l-.014-.01c.523.325.946 1.19.946 1.696a5.444 5.444 0 0 0 5.425 5.427c1.417 0 2.756-.427 3.77-1.285s1.66-2.173 1.66-3.664l-.003-.808l-.004-.092a8.75 8.75 0 0 1 1.004-4.75V61.5c.434-.804.707-1.697.884-2.621c1.963-.514 3.917-1.088 5.83-1.809l.005-.002a9.5 9.5 0 0 1 2.08-.54l.004-.001a8.39 8.39 0 0 0 7.23-8.3c0-4.612-3.765-8.378-8.378-8.378c-1.33 0-2.567.355-3.683.907c-1.606-3.64-5.225-6.192-9.447-6.192c-4.792 0-8.802 3.298-9.973 7.73c-1.763-2.057-4.318-3.42-7.232-3.42c-2.579 0-4.847 1.098-6.577 2.76c-.66-4.875-4.811-8.663-9.862-8.663zm0 2.288a7.692 7.692 0 0 1 7.267 10.265a1.144 1.144 0 0 0 .894 1.506l.028.005a1.144 1.144 0 0 0 1.235-.757l.001.003l.002-.005l.037-.023a7.32 7.32 0 0 1 6.977-5.095a7.32 7.32 0 0 1 6.958 5.042a1.144 1.144 0 0 0 2.224-.476a8.046 8.046 0 0 1 8.023-8.876a8.06 8.06 0 0 1 7.688 5.629a1.144 1.144 0 0 0 1.38.762l.801-.21a1.1 1.1 0 0 0 .274-.111a6.04 6.04 0 0 1 2.986-.784a6.073 6.073 0 0 1 6.09 6.09a6.08 6.08 0 0 1-5.255 6.034h-.005a11.8 11.8 0 0 0-2.585.672a57 57 0 0 1-6.272 1.944a1.14 1.14 0 0 0-.862.995a6.8 6.8 0 0 1-.78 2.548l-.001.004a11.04 11.04 0 0 0-1.27 5.996l-.002-.094l.004.826c0 .875-.313 1.465-.85 1.918c-.535.454-1.34.746-2.293.746a3.123 3.123 0 0 1-3.14-3.14a4.28 4.28 0 0 0-2.024-3.639l-.01-.01a6.85 6.85 0 0 1-2.839-3.394a1.14 1.14 0 0 0-1.105-.732c-12.054.406-23.122-1.72-28.638-3.207l-.014-.004a48 48 0 0 0-4.472-1.038l.02.003c-2.84-.563-4.999-3.046-4.999-6.049a6.07 6.07 0 0 1 5.873-6.08a1.144 1.144 0 0 0 1.085-.938a7.695 7.695 0 0 1 7.578-6.331zM42.134.018a1.14 1.14 0 0 0-.9.811c-1.682 5.888.956 11.472 4.474 15.656a32 32 0 0 0 2.54 2.679a10.9 10.9 0 0 0-3.55.1c-6.317 1.244-11.696 5.254-14.618 13.505c-1.198 3.384-1.251 6.903-.865 10.1a6.1 6.1 0 0 1 1.8-.339a1.1 1.1 0 0 0 .437-.172c-.32-2.887-.225-5.978.784-8.827c2.713-7.662 7.224-10.906 12.902-12.024c1.956-.384 3.544-.057 5.28.508c.868.284 1.763.633 2.724.966l.178.055c.91.31 1.875.604 2.934.807a1.144 1.144 0 0 0 1.344-1.311a13 13 0 0 1-.003-4.198c.047-.28.088-.563.148-.837c.35-1.56.947-2.992 1.65-4.268a19.8 19.8 0 0 1 3.535-4.598c.376.285.753.54 1.128.96c.183.205.172.215.312.388c-1.77 1.643-5.705 6.102-5.078 13.084a1.144 1.144 0 0 0 1.181 1.039c2.503-.09 4.174-.92 5.634-1.593s2.712-1.216 4.968-1.146c4.667.147 8.737 3.814 10.339 6.051c1.73 2.634 3.858 5.908 3.513 14.883v.038a6 6 0 0 1 1.524-.197q.388.002.764.054c.316-9.267-2.162-13.403-3.908-16.06l-.023-.038c-1.945-2.722-6.366-6.837-12.137-7.017c-2.681-.083-4.49.66-5.996 1.354c-1.161.535-2.246.944-3.571 1.175c.009-6.858 5.037-10.568 5.037-10.568a1.144 1.144 0 0 0 .261-1.584s-.461-.654-1.112-1.385c-.65-.73-1.438-1.575-2.507-2.021a1.14 1.14 0 0 0-1.201.2a23 23 0 0 0-4.665 5.877c-.256.464-.48.971-.705 1.48c-.493-1.63-1.16-3.144-2.035-4.54c-2.415-3.85-6.317-6.742-11.89-8.982a1.14 1.14 0 0 0-.627-.065m1.036 2.775c4.533 2.018 7.624 4.428 9.541 7.486c1.4 2.23 2.21 4.867 2.548 7.989c.014.151.024.311.038.466v.001c.085.902.137 1.834.148 2.818c-.33-.175-.724-.428-1.097-.655c-.243-.148-.457-.254-.712-.423c-1.952-1.284-4.252-3.17-6.178-5.46c-2.944-3.504-4.99-7.784-4.288-12.223zm44.049 51.484a11.8 11.8 0 0 0-2.527.66a53 53 0 0 1-1.928.681c-.061.115-.088.172-.153.298c-.033.064-.148.236-.191.313h2.847v3.36a3.07 3.07 0 0 0 3.055 3.052h7.085a7.45 7.45 0 0 1 7.45 7.45v30.956a7.46 7.46 0 0 1-2.192 5.277a7.46 7.46 0 0 1-3.822 2.034a7.5 7.5 0 0 1-1.464.14h-.005c-2.39.005-4.898 0-6.988-.028a3.055 3.055 0 0 0-3.116 3.05c0 2.5 0 6.735-.01 8.553v.005a.76.76 0 0 1-.265.571c-1.157.863-4.513 2.628-10.991 3.83a65 65 0 0 1-4.268.64c-3.104.367-6.737.597-10.957.597c-16.572 0-24.463-2.779-26.608-4.01a.76.76 0 0 1-.35-.633l-.138-64.843h4.063c-.057-.105-.086-.176-.142-.28c-.326-.083-.699-.17-.996-.25l-.014-.003a48 48 0 0 0-4.472-1.038l.018.004a6 6 0 0 1-.517-.128a1.14 1.14 0 0 0-.228.554s.123 57.552.14 65.988a3.06 3.06 0 0 0 1.412 2.569l.042.023c2.862 1.657 10.915 4.332 27.789 4.332c17.268 0 25.067-3.613 27.63-5.55l.037-.032a3.05 3.05 0 0 0 1.101-2.342c.01-1.837.01-6.06.01-8.558a.76.76 0 0 1 .228-.546v-.001a.76.76 0 0 1 .553-.218h.01c2.11.028 4.628.032 7.025.028a9.74 9.74 0 0 0 9.772-9.737l.001-30.955a9.74 9.74 0 0 0-9.739-9.739h-7.084a.75.75 0 0 1-.765-.764v-4.503a1.14 1.14 0 0 0-.336-.81zm1.58 13.728a3.5 3.5 0 0 0-1.351.269a3.5 3.5 0 0 0-1.147.764v.001a3.5 3.5 0 0 0-.764 1.145a3.5 3.5 0 0 0-.269 1.352v27.78a3.5 3.5 0 0 0 .27 1.352a3.5 3.5 0 0 0 .763 1.146a3.5 3.5 0 0 0 1.147.764a3.5 3.5 0 0 0 1.351.27h6.082a3.5 3.5 0 0 0 1.352-.27a3.5 3.5 0 0 0 1.145-.764a3.5 3.5 0 0 0 .764-1.146a3.5 3.5 0 0 0 .27-1.351v-27.78a3.5 3.5 0 0 0-.27-1.352a3.5 3.5 0 0 0-.763-1.145h-.001a3.5 3.5 0 0 0-1.147-.765a3.5 3.5 0 0 0-1.35-.27zm0 2.288h6.082a1.244 1.244 0 0 1 1.243 1.242v27.782a1.243 1.243 0 0 1-1.243 1.243H88.8a1.24 1.24 0 0 1-.879-.363h-.001a1.24 1.24 0 0 1-.363-.88v-27.78a1.24 1.24 0 0 1 .767-1.15q.226-.092.476-.093z"/&gt;&lt;path fill="#d1d3d4" d="M43.171 2.793c-.701 4.438 1.344 8.719 4.289 12.222c2.567 3.053 5.799 5.387 7.988 6.538c-.052-4.604-.87-8.3-2.734-11.272c-1.92-3.058-5.01-5.47-9.543-7.486zm19.76 5.838a19.8 19.8 0 0 0-3.535 4.598c-1.408 2.552-2.392 5.73-1.797 9.303a1.144 1.144 0 0 1-1.343 1.311c-2.253-.431-4.1-1.262-5.836-1.828c-1.735-.567-3.323-.892-5.28-.507c-5.68 1.117-10.19 4.36-12.902 12.023c-.449 1.27-.708 2.59-.84 3.916c1.78-2.693 4.817-4.474 8.28-4.474c5.051 0 9.2 3.79 9.863 8.663c1.728-1.66 3.998-2.76 6.577-2.76c2.913 0 5.467 1.363 7.231 3.42c1.171-4.431 5.18-7.729 9.973-7.729c4.222 0 7.84 2.552 9.448 6.19a9 9 0 0 1 2.172-.739c-.076-7.241-1.956-10.21-3.527-12.602c-1.603-2.237-5.672-5.905-10.339-6.053c-2.256-.069-3.51.475-4.968 1.147c-1.46.673-3.131 1.504-5.634 1.593a1.144 1.144 0 0 1-1.18-1.04c-.63-6.982 3.307-11.44 5.076-13.084c-.14-.172-.128-.182-.31-.387c-.376-.42-.753-.675-1.129-.961"/&gt;&lt;path fill="#fbb040" d="M36.042 58.416v55.313a1.91 1.91 0 0 0 .955 1.656c2.417 1.151 9.427 3.9 21.716 3.9c12.372 0 19.173-3.34 21.451-4.718a1.9 1.9 0 0 0 .873-1.599c.005-7.316.005-48.47.005-54.473c-.456.128-.91.267-1.369.386a11 11 0 0 1-.345 1.356q-.213.661-.536 1.265l-.003.004a8.76 8.76 0 0 0-1.002 4.75l.004.093l.002.806a4.8 4.8 0 0 1-.45 2.07a4.7 4.7 0 0 1-.522.87a4.6 4.6 0 0 1-.688.724a5 5 0 0 1-.817.563a5.5 5.5 0 0 1-.918.402a6 6 0 0 1-.99.24q-.511.081-1.044.081a5.4 5.4 0 0 1-3.027-.93a5.5 5.5 0 0 1-1.972-2.39a5.4 5.4 0 0 1-.427-2.108c0-.126-.028-.275-.074-.431a2.6 2.6 0 0 0-.204-.483a2.6 2.6 0 0 0-.3-.45a1.6 1.6 0 0 0-.368-.33l.014.008a9 9 0 0 1-1.058-.754a9 9 0 0 1-.933-.899a9 9 0 0 1-.798-1.023a10 10 0 0 1-.653-1.132c-1.508.038-2.998.038-4.461.01a104 104 0 0 1-4.304-.18a109 109 0 0 1-4.099-.334a112 112 0 0 1-7.384-.991a104 104 0 0 1-3.19-.59a91 91 0 0 1-2.788-.604l-.296-.075zm6.615 3.51a2.6 2.6 0 0 1 1.007.202a2.6 2.6 0 0 1 .853.57a2.6 2.6 0 0 1 .57.852a2.6 2.6 0 0 1 .202 1.007v45.748a2.6 2.6 0 0 1-.033.412a2.6 2.6 0 0 1-.096.402a2.6 2.6 0 0 1-.156.382a2.6 2.6 0 0 1-.218.352a3 3 0 0 1-.267.314a2.6 2.6 0 0 1-.314.268a2.6 2.6 0 0 1-.353.217a2.6 2.6 0 0 1-.382.156a2.6 2.6 0 0 1-.402.098a3 3 0 0 1-.41.032a2.6 2.6 0 0 1-1.01-.2a2.6 2.6 0 0 1-.852-.57a2.6 2.6 0 0 1-.57-.854a2.6 2.6 0 0 1-.2-1.007V64.56a2.6 2.6 0 0 1 .2-1.008a2.6 2.6 0 0 1 .57-.853a2.6 2.6 0 0 1 .854-.57a2.6 2.6 0 0 1 1.007-.2z"/&gt;&lt;path fill="#ffdb96" d="M42.66 61.924a2.63 2.63 0 0 0-2.632 2.63v45.749a2.63 2.63 0 0 0 2.632 2.632a2.63 2.63 0 0 0 2.632-2.632V64.555a2.63 2.63 0 0 0-2.632-2.631"/&gt;&lt;path fill="#fff" d="M39.676 35.259a7.695 7.695 0 0 0-7.578 6.331a1.144 1.144 0 0 1-1.084.939a6.07 6.07 0 0 0-5.872 6.08c0 3.001 2.157 5.485 4.998 6.049l-.02-.004a48 48 0 0 1 4.473 1.038l.014.005c5.517 1.485 16.585 3.612 28.638 3.205a1.14 1.14 0 0 1 1.106.733a6.85 6.85 0 0 0 2.84 3.394l.01.01a4.28 4.28 0 0 1 2.025 3.638a3.123 3.123 0 0 0 3.14 3.142c.952 0 1.757-.294 2.293-.747c.536-.454.85-1.043.85-1.917l-.004-.805a11.04 11.04 0 0 1 1.27-5.924l.003-.004a6.8 6.8 0 0 0 .78-2.548a1.14 1.14 0 0 1 .861-.994a57 57 0 0 0 6.272-1.945a11.8 11.8 0 0 1 2.585-.67h.005a6.08 6.08 0 0 0 5.255-6.036a6.073 6.073 0 0 0-6.09-6.09c-1.088 0-2.1.285-2.986.784a1.1 1.1 0 0 1-.274.111l-.801.21a1.144 1.144 0 0 1-1.381-.762a8.06 8.06 0 0 0-7.687-5.629a8.046 8.046 0 0 0-8.022 8.876a1.144 1.144 0 0 1-2.225.476a7.32 7.32 0 0 0-6.957-5.042a7.32 7.32 0 0 0-6.977 5.094l-.037.023v.005l-.003-.004a1.144 1.144 0 0 1-1.235.758l-.028-.004a1.144 1.144 0 0 1-.894-1.507a7.692 7.692 0 0 0-7.267-10.266zm45.592 21.897a45 45 0 0 1-2.658.896c-.519.16-1.043.296-1.565.441c0 6 0 47.153-.005 54.473a1.9 1.9 0 0 1-.873 1.6c-.284.172-.64.374-1.067.597c-.428.223-.93.467-1.504.72a31 31 0 0 1-1.954.78a37 37 0 0 1-2.414.777a44 44 0 0 1-4.512 1.025a51 51 0 0 1-3.62.5q-.968.1-2 .171a63 63 0 0 1-4.379.146a75 75 0 0 1-4.364-.12a69 69 0 0 1-1.997-.142a66 66 0 0 1-3.635-.41a59 59 0 0 1-1.64-.26a53 53 0 0 1-2.925-.586a45 45 0 0 1-2.464-.642a38 38 0 0 1-2.007-.645a31 31 0 0 1-1.562-.599A24 24 0 0 1 37 115.38a1.91 1.91 0 0 1-.957-1.656v-55.31a74 74 0 0 1-2.046-.513l-.014-.004a46 46 0 0 0-2.123-.547l-.177-.038l.137 63.761a.78.78 0 0 0 .349.634c.268.154.626.333 1.08.525c.453.195 1.002.405 1.651.621c.651.216 1.402.44 2.26.664c.86.221 1.825.443 2.902.655c1.079.212 2.268.416 3.579.6q1.962.28 4.288.49a105 105 0 0 0 5.034.332a133 133 0 0 0 5.813.122a108 108 0 0 0 5.898-.16a90 90 0 0 0 2.632-.189a79 79 0 0 0 2.428-.247a70 70 0 0 0 2.232-.3a62 62 0 0 0 2.036-.343a54 54 0 0 0 2.285-.473a45 45 0 0 0 2.003-.51a38 38 0 0 0 1.732-.528a31 31 0 0 0 1.472-.53q.671-.261 1.22-.512q.55-.25.985-.48a13 13 0 0 0 .756-.432a8 8 0 0 0 .537-.364a.8.8 0 0 0 .196-.256a.7.7 0 0 0 .07-.313v-.005c.01-1.818.01-6.053.01-8.553a3.05 3.05 0 0 1 1.93-2.836a3.1 3.1 0 0 1 1.186-.216c2.089.028 4.599.032 6.986.028h.01a7.5 7.5 0 0 0 1.464-.14a7.46 7.46 0 0 0 5.442-4.452a7.5 7.5 0 0 0 .571-2.858V70.093a7.45 7.45 0 0 0-1.686-4.721a7.46 7.46 0 0 0-5.765-2.73h-7.084a3 3 0 0 1-1.701-.525a3.1 3.1 0 0 1-.826-.826a3 3 0 0 1-.526-1.7zm3.53 10.846h6.082a3.5 3.5 0 0 1 1.35.269a3.5 3.5 0 0 1 1.147.764a3.5 3.5 0 0 1 .765 1.147a3.5 3.5 0 0 1 .269 1.35v27.782a3.5 3.5 0 0 1-.268 1.35a3.5 3.5 0 0 1-.764 1.146h-.002a3.5 3.5 0 0 1-1.144.764a3.5 3.5 0 0 1-1.351.27h-6.084a3.5 3.5 0 0 1-1.351-.268a3.5 3.5 0 0 1-1.145-.765a3.5 3.5 0 0 1-.765-1.147a3.5 3.5 0 0 1-.268-1.35V71.532a3.5 3.5 0 0 1 .267-1.351a3.5 3.5 0 0 1 .764-1.146h.002a3.5 3.5 0 0 1 1.146-.765a3.5 3.5 0 0 1 1.35-.269z"/&gt;&lt;/svg&gt;
&lt;/span&gt; macOS Homebrew
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install --cask docker
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#0078d4" d="M67.328 67.331h60.669V128H67.328zm-67.325 0h60.669V128H.003zM67.328 0h60.669v60.669H67.328zM.003 0h60.669v60.669H.003z"/&gt;&lt;/svg&gt;
&lt;/span&gt; Windows WinGet
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-pwsh" data-lang="pwsh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;winget&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;Docker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;DockerDesktop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="prüfen-der-installation"&gt;Prüfen der Installation&lt;/h2&gt;
&lt;p&gt;Nach der Installation und Start von Docker Desktop, sollte dieser in erster Linie in der Statusleiste als Icon
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M73.8 50.8h11.3v11.5h5.7c2.6 0 5.3-.5 7.8-1.3c1.2-.4 2.6-1 3.8-1.7c-1.6-2.1-2.4-4.7-2.6-7.3c-.3-3.5.4-8.1 2.8-10.8l1.2-1.4l1.4 1.1c3.6 2.9 6.5 6.8 7.1 11.4c4.3-1.3 9.3-1 13.1 1.2l1.5.9l-.8 1.6c-3.2 6.2-9.9 8.2-16.4 7.8c-9.8 24.3-31 35.8-56.8 35.8c-13.3 0-25.5-5-32.5-16.8l-.1-.2l-1-2.1c-2.4-5.2-3.1-10.9-2.6-16.6l.2-1.7h9.6V50.8h11.3V39.6h22.5V28.3h13.5z" clip-rule="evenodd"/&gt;&lt;path fill="#00aada" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7H18.6c-.6 6.2.5 11.9 3 16.8l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5 1.1-8.3 1.3h-.6c-1.3.1-2.7.1-4.2.1c-1.6 0-3.1 0-4.9-.1c6 6.8 15.4 10.8 27.2 10.8c25 0 46.2-11.1 55.5-35.9c6.7.7 13.1-1 16-6.7c-4.5-2.7-10.5-1.8-13.9-.1"/&gt;&lt;path fill="#28b8eb" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7h-68c-.3 9.5 3.2 16.7 9.5 21c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4l-.1-.1c8.5 4.4 20.8 4.3 35-1.1c15.8-6.1 30.6-17.7 40.9-30.9c-.2.1-.4.1-.5.2"/&gt;&lt;path fill="#028bb8" d="M18.7 71.8c.4 3.3 1.4 6.4 2.9 9.3l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4h-.4c-1.3.1-2.7.1-4.1.1c-1.6 0-3.2 0-4.9-.1c6 6.8 15.5 10.8 27.3 10.8c21.4 0 40-8.1 50.8-26H18.7z"/&gt;&lt;path fill="#019bc6" d="M23.5 71.8c1.3 5.8 4.3 10.4 8.8 13.5c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.6 1.4c8.5 4.4 20.8 4.3 34.9-1.1c8.5-3.3 16.8-8.2 24.2-14.1z"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M28.4 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3-12h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M39.6 52.7h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M50.9 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M50.9 41.5h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3.1 10.4H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M62.2 41.5H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M62.2 30.2H72V40h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M73.5 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#d4eef1" fill-rule="evenodd" d="M48.8 78.3c1.5 0 2.7 1.2 2.7 2.7s-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7s1.2-2.7 2.7-2.7" clip-rule="evenodd"/&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M48.8 79.1c.2 0 .5 0 .7.1c-.2.1-.4.4-.4.7c0 .4.4.8.8.8c.3 0 .6-.2.7-.4c.1.2.1.5.1.7c0 1.1-.9 1.9-1.9 1.9c-1.1 0-1.9-.9-1.9-1.9s.8-1.9 1.9-1.9M1.1 72.8h125.4c-2.7-.7-8.6-1.6-7.7-5.2c-5 5.7-16.9 4-20 1.2c-3.4 4.9-23 3-24.3-.8c-4.2 5-17.3 5-21.5 0c-1.4 3.8-21 5.7-24.3.8c-3 2.8-15 4.5-20-1.2c1.1 3.5-4.9 4.5-7.6 5.2" clip-rule="evenodd"/&gt;&lt;path fill="#bfdbe0" d="M56 97.8c-6.7-3.2-10.3-7.5-12.4-12.2c-2.5.7-5.5 1.2-8.9 1.4c-1.3.1-2.7.1-4.1.1c-1.7 0-3.4 0-5.2-.1c6 6 13.6 10.7 27.5 10.8z"/&gt;&lt;path fill="#d4eef1" d="M46.1 89.9c-.9-1.3-1.8-2.8-2.5-4.3c-2.5.7-5.5 1.2-8.9 1.4c2.3 1.2 5.7 2.4 11.4 2.9"/&gt;&lt;/svg&gt;
&lt;/span&gt; angezeigt werden. Wenn dies nicht der Fall ist, sollten Sie die Installation überprüfen.&lt;/p&gt;
&lt;h3 id="in-terminal--powershell"&gt;In Terminal / PowerShell&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: 29.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; API version: 1.52
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Go version: go1.25.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Git commit: 890dcca
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Built: Tue Dec &lt;span class="m"&gt;2&lt;/span&gt; 21:54:24 &lt;span class="m"&gt;2025&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OS/Arch: darwin/arm64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Context: desktop-linux
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: Docker Desktop 4.54.0 &lt;span class="o"&gt;(&lt;/span&gt;212467&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Engine:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: 29.1.2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; API version: 1.52 &lt;span class="o"&gt;(&lt;/span&gt;minimum version 1.44&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Go version: go1.25.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Git commit: de45c2a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Built: Tue Dec &lt;span class="m"&gt;2&lt;/span&gt; 21:55:52 &lt;span class="m"&gt;2025&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; OS/Arch: linux/arm64
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Experimental: &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; containerd:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: v2.2.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; GitCommit: 1c4457e00facac03ce1d75f7b6777a7a851e5c41
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; runc:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: 1.3.4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; GitCommit: v1.3.4-0-gd6d73eb8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker-init:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Version: 0.19.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; GitCommit: de40ad0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-desktop-ui-starten"&gt;Docker Desktop UI starten&lt;/h2&gt;
&lt;p&gt;Nachdem das Docker-Desktop-Symbol in der Statusleiste angezeigt wurde, können Sie das Docker Desktop Dashboard starten. Dies ist entweder über das Startmenü oder durch Klicken auf das Symbol
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M73.8 50.8h11.3v11.5h5.7c2.6 0 5.3-.5 7.8-1.3c1.2-.4 2.6-1 3.8-1.7c-1.6-2.1-2.4-4.7-2.6-7.3c-.3-3.5.4-8.1 2.8-10.8l1.2-1.4l1.4 1.1c3.6 2.9 6.5 6.8 7.1 11.4c4.3-1.3 9.3-1 13.1 1.2l1.5.9l-.8 1.6c-3.2 6.2-9.9 8.2-16.4 7.8c-9.8 24.3-31 35.8-56.8 35.8c-13.3 0-25.5-5-32.5-16.8l-.1-.2l-1-2.1c-2.4-5.2-3.1-10.9-2.6-16.6l.2-1.7h9.6V50.8h11.3V39.6h22.5V28.3h13.5z" clip-rule="evenodd"/&gt;&lt;path fill="#00aada" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7H18.6c-.6 6.2.5 11.9 3 16.8l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5 1.1-8.3 1.3h-.6c-1.3.1-2.7.1-4.2.1c-1.6 0-3.1 0-4.9-.1c6 6.8 15.4 10.8 27.2 10.8c25 0 46.2-11.1 55.5-35.9c6.7.7 13.1-1 16-6.7c-4.5-2.7-10.5-1.8-13.9-.1"/&gt;&lt;path fill="#28b8eb" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7h-68c-.3 9.5 3.2 16.7 9.5 21c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4l-.1-.1c8.5 4.4 20.8 4.3 35-1.1c15.8-6.1 30.6-17.7 40.9-30.9c-.2.1-.4.1-.5.2"/&gt;&lt;path fill="#028bb8" d="M18.7 71.8c.4 3.3 1.4 6.4 2.9 9.3l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4h-.4c-1.3.1-2.7.1-4.1.1c-1.6 0-3.2 0-4.9-.1c6 6.8 15.5 10.8 27.3 10.8c21.4 0 40-8.1 50.8-26H18.7z"/&gt;&lt;path fill="#019bc6" d="M23.5 71.8c1.3 5.8 4.3 10.4 8.8 13.5c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.6 1.4c8.5 4.4 20.8 4.3 34.9-1.1c8.5-3.3 16.8-8.2 24.2-14.1z"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M28.4 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3-12h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M39.6 52.7h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M50.9 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M50.9 41.5h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3.1 10.4H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M62.2 41.5H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M62.2 30.2H72V40h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M73.5 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#d4eef1" fill-rule="evenodd" d="M48.8 78.3c1.5 0 2.7 1.2 2.7 2.7s-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7s1.2-2.7 2.7-2.7" clip-rule="evenodd"/&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M48.8 79.1c.2 0 .5 0 .7.1c-.2.1-.4.4-.4.7c0 .4.4.8.8.8c.3 0 .6-.2.7-.4c.1.2.1.5.1.7c0 1.1-.9 1.9-1.9 1.9c-1.1 0-1.9-.9-1.9-1.9s.8-1.9 1.9-1.9M1.1 72.8h125.4c-2.7-.7-8.6-1.6-7.7-5.2c-5 5.7-16.9 4-20 1.2c-3.4 4.9-23 3-24.3-.8c-4.2 5-17.3 5-21.5 0c-1.4 3.8-21 5.7-24.3.8c-3 2.8-15 4.5-20-1.2c1.1 3.5-4.9 4.5-7.6 5.2" clip-rule="evenodd"/&gt;&lt;path fill="#bfdbe0" d="M56 97.8c-6.7-3.2-10.3-7.5-12.4-12.2c-2.5.7-5.5 1.2-8.9 1.4c-1.3.1-2.7.1-4.1.1c-1.7 0-3.4 0-5.2-.1c6 6 13.6 10.7 27.5 10.8z"/&gt;&lt;path fill="#d4eef1" d="M46.1 89.9c-.9-1.3-1.8-2.8-2.5-4.3c-2.5.7-5.5 1.2-8.9 1.4c2.3 1.2 5.7 2.4 11.4 2.9"/&gt;&lt;/svg&gt;
&lt;/span&gt; in der Statusleiste möglich.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/install/docker_desktop_dashboard.png"
alt="Docker Desktop Dashboard"&gt;&lt;figcaption&gt;
&lt;h4&gt;Docker Desktop Dashboard&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Installation von Git</title><link>https://kurse.richter.consulting/courses/git/installation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/installation/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kurse$ git --version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git version 2.33.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;kurse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="mf"&gt;2.33&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;windows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wird statt einer Versionsangabe eine Fehlermeldung angezeigt, dass das &lt;code&gt;git&lt;/code&gt; Befehl nicht gefunden wurde, muss git zuerst installiert werden.&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Der Befehl &amp;ldquo;git&amp;rdquo; ist entweder falsch geschrieben oder konnte nicht gefunden werden.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Folgen Sie dazu der Installationsanleitung für Ihr Betriebssystem von der offiziellen
.&lt;/p&gt;</description></item><item><title>Ersten Container ausführen</title><link>https://kurse.richter.consulting/courses/container/first_container/</link><pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/first_container/</guid><description>&lt;p&gt;Nachdem Docker Desktop auf unserem System läuft, können wir nun ein erstes Container auf unserem Rechner ausführen. Dazu werden wir die das mitinstallierte Docker CLI nutzen.&lt;/p&gt;
&lt;h2 id="nginx-webserver-ausführen"&gt;nginx Webserver ausführen&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --name mein-server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 1080:80 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d nginx:alpine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --name mein-server -p 1080:80 -d nginx:alpine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unable to find image &lt;span class="s1"&gt;&amp;#39;nginx:alpine&amp;#39;&lt;/span&gt; locally
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alpine: Pulling from library/nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e1779b8a5a13: Download &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;81eecc9295df: Download &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;9afea992cb63: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e6b7df06dc76: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;223f9efb3159: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0bd713040ebb: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d85e26d0c84d: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2422bf732277: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e350a0f963e3: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;29b7c987abf6: Pull &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Digest: sha256:289decab414250121a93c3f1b8316b9c69906de3a4993757c424cb964169ad42
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Status: Downloaded newer image &lt;span class="k"&gt;for&lt;/span&gt; nginx:alpine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;76c073965f57bc7351a7259b6e71b70a990cb42bcc4cda7ee41c6f38bb11963d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker run&lt;/code&gt; startet ein neues Container&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--name &amp;lt;eingener_container_name&amp;gt;&lt;/code&gt; gibt dem Container den Namen &lt;code&gt;mein-server&lt;/code&gt;. Dies ist optional. Wird kein Name angegeben, &amp;ldquo;würfelt&amp;rdquo; Decker einen aus.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p 1080:80&lt;/code&gt; Durchreichen eines Ports aus dem Container (hier Port &lt;code&gt;80&lt;/code&gt; des nginx Servers) zu dem Host-Port (hier &lt;code&gt;1080&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d&lt;/code&gt; Starten Container als &amp;ldquo;Detached&amp;rdquo; (Hintergrundprozess), so dass die Kommandozeile weiter genutzt werden kann.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx:alpine&lt;/code&gt; ist der Image, das wir verwenden. &lt;code&gt;nginx&lt;/code&gt; ist dabei der Name des Images (Repository). &lt;code&gt;alpine&lt;/code&gt; ist ein Tag (Version).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In der Ausgabe sehen wir, dass Docker am Anfang das Image nicht hat (&lt;code&gt;Unable to find image 'nginx:alpine' locally&lt;/code&gt;). Aus diesem Grund stößt dieser an, das Image aus dem Docker Hub herunterzuladen. Dies kann einige Zeit dauern, abhängig von der Internetverbindung und der Größe des Images. In unserem Fall ist das Image sehr klein (ca. 20MB).&lt;/p&gt;
&lt;p&gt;Nun können wir über &lt;code&gt;http://localhost:1080&lt;/code&gt; auf unseren neuen Webserver zugreifen.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/first_container/nginx_base_container.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Container liefert Web-Inhalt&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="container-stoppen-und-löschen"&gt;Container stoppen und löschen&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker stop mein-server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker rm mein-server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="nginx-mit-eigenen-inhalt-ausführen"&gt;nginx mit eigenen Inhalt ausführen&lt;/h2&gt;
&lt;p&gt;Statt der langweiligen Standardseite von nginx können wir auch diesen dazu bewegen, unsere eigen statische Seite auszuliefern. Dazu erstellen wir zuerst einen Ordner und legen da eine einfache HTML Seite ab.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Beispiel Seite finden Sie in dem verlinkten
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;g fill="#181616"&gt;&lt;path fill-rule="evenodd" d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388c0 26.682 17.303 49.317 41.297 57.303c3.017.56 4.125-1.31 4.125-2.905c0-1.44-.056-6.197-.082-11.243c-16.8 3.653-20.345-7.125-20.345-7.125c-2.747-6.98-6.705-8.836-6.705-8.836c-5.48-3.748.413-3.67.413-3.67c6.063.425 9.257 6.223 9.257 6.223c5.386 9.23 14.127 6.562 17.573 5.02c.542-3.903 2.107-6.568 3.834-8.076c-13.413-1.525-27.514-6.704-27.514-29.843c0-6.593 2.36-11.98 6.223-16.21c-.628-1.52-2.695-7.662.584-15.98c0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033c11.526-7.813 16.59-6.19 16.59-6.19c3.287 8.317 1.22 14.46.593 15.98c3.872 4.23 6.215 9.617 6.215 16.21c0 23.194-14.127 28.3-27.574 29.796c2.167 1.874 4.097 5.55 4.097 11.183c0 8.08-.07 14.583-.07 16.572c0 1.607 1.088 3.49 4.148 2.897c23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z" clip-rule="evenodd"/&gt;&lt;path d="M26.484 91.806c-.133.3-.605.39-1.035.185c-.44-.196-.685-.605-.543-.906c.13-.31.603-.395 1.04-.188c.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28c-.396-.42-.47-.983-.177-1.254c.298-.266.844-.14 1.24.28c.394.426.472.984.17 1.255zm2.382 3.477c-.37.258-.976.017-1.35-.52c-.37-.538-.37-1.183.01-1.44c.373-.258.97-.025 1.35.507c.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23c-.527-.487-.674-1.18-.343-1.544c.336-.366 1.045-.264 1.564.23c.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486c-.683-.207-1.13-.76-.99-1.238c.14-.477.823-.7 1.512-.485c.683.206 1.13.756.988 1.237m4.943.361c.017.498-.563.91-1.28.92c-.723.017-1.308-.387-1.315-.877c0-.503.568-.91 1.29-.924c.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117c-.7.13-1.35-.172-1.44-.653c-.086-.498.422-.997 1.122-1.126c.714-.123 1.354.17 1.444.663zm0 0"/&gt;&lt;/g&gt;&lt;/svg&gt;
&lt;/span&gt;
im Ordner &lt;code&gt;nginx-site&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --name mein-server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 1080:80 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v ./nginx-site:/usr/share/nginx/html:ro &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d nginx:alpine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-v &amp;lt;ordner/pfad/auf/dem/host&amp;gt;:/usr/share/nginx/html:ro&lt;/code&gt; Mapping für Speicher (Volume)
&lt;ul&gt;
&lt;li&gt;der 2. Teil nach dem &lt;code&gt;:&lt;/code&gt; ist der Ordner innerhalb vom Container, das auf unseren lokalen Ordner gemappt werden soll. nginx erwartet Web-Inhalt in dem Ordner &lt;code&gt;/usr/share/nginx/html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ro&lt;/code&gt; am Ende steht für &lt;code&gt;read only&lt;/code&gt;. D.h. der Container kann nur lesend auf unseren lokalen Ordner zugreifen.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/first_container/nginx_own_page.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Eigene Web-Site mit nginx&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Initialisierung eines lokalen Repositorys</title><link>https://kurse.richter.consulting/courses/git/init/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/init/</guid><description>
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Als ein &lt;strong&gt;Repository&lt;/strong&gt; bei &lt;strong&gt;git&lt;/strong&gt; wird ein Ordner bezeichnet, der unter Versionskontrolle von git steht.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="ordner-anlegen"&gt;Ordner anlegen&lt;/h2&gt;
&lt;p&gt;Als erstes legen wir einen Ordner an, den wir gleich unter die Versionsverwaltung stellen wollen. Aktuell werden wir es mit einem leeren Ordner tun, das Gleiche lässt sich auch mit einem vorhandenen Ordner erledigen, wenn Sie desen Inhalt versionieren wollen.&lt;/p&gt;
&lt;p&gt;Wechseln Sie in den neu erzeugten Ordner.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;src$ mkdir repo_1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;src$ ls -la
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;src$ &lt;span class="nb"&gt;cd&lt;/span&gt; repo_1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows (Power Shell Core)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;New-Item&lt;/span&gt; &lt;span class="n"&gt;repo_1&lt;/span&gt; &lt;span class="n"&gt;-Type&lt;/span&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;kurse&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;LastWriteTime&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="p"&gt;-------------&lt;/span&gt; &lt;span class="p"&gt;------&lt;/span&gt; &lt;span class="p"&gt;----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="mf"&gt;15.09&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;08&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;05&lt;/span&gt; &lt;span class="n"&gt;repo_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="repository-initialisieren"&gt;Repository initialisieren&lt;/h2&gt;
&lt;p&gt;Nun initialisieren wir ein git Repository mit dem &lt;code&gt;init&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; Befehl von git.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Initialized empty Git repository in /Users/kurse/src/repo_1/.git/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls -la
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;total &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drwxrwxrwx &lt;span class="m"&gt;1&lt;/span&gt; kurse kurse &lt;span class="m"&gt;4096&lt;/span&gt; Sep &lt;span class="m"&gt;15&lt;/span&gt; 08:10 .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drwxrwxrwx &lt;span class="m"&gt;1&lt;/span&gt; kurse kurse &lt;span class="m"&gt;4096&lt;/span&gt; Sep &lt;span class="m"&gt;15&lt;/span&gt; 08:05 ..
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drwxrwxrwx &lt;span class="m"&gt;1&lt;/span&gt; kurse kurse &lt;span class="m"&gt;4096&lt;/span&gt; Sep &lt;span class="m"&gt;15&lt;/span&gt; 08:10 .git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows (Power Shell Core)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Initialized&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt; &lt;span class="n"&gt;Git&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;kurse&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;/.&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Get-ChildItem&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;-Force&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;kurse&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;LastWriteTime&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="p"&gt;-------------&lt;/span&gt; &lt;span class="p"&gt;------&lt;/span&gt; &lt;span class="p"&gt;----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-h&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;15.09&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;08&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;12&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dabei wird das Verzeichnis unter Versionskontrolle gestellt. Das ist an dem versteckten Ordner &lt;code&gt;.git&lt;/code&gt; gut zu sehen. In diesem werden alle Informationen zu den Versionen gespeichert.&lt;/p&gt;
&lt;h2 id="prüfen-des-aktuellen-zustandes-von-repository"&gt;Prüfen des aktuellen Zustandes von Repository&lt;/h2&gt;
&lt;p&gt;Den aktuellen Zustand des Ordners, aus Sicht von git, können wir mit dem Befehl &lt;code&gt;status&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; abrufen. Dieser zeigt, ob neue Dateien zu der Versionsverwaltung hinzugefügt werden können, ob geänderte Dateien vorliegen usw.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No commits yet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing to commit &lt;span class="o"&gt;(&lt;/span&gt;create/copy files and use &lt;span class="s2"&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;On&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;commits&lt;/span&gt; &lt;span class="n"&gt;yet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;nothing&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;copy &lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bei einem neu angelegten Repository ist der Status sauber. Es sind ja keine Dateien versioniert und es liegen keine zum Versionieren vor.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Erster Container für Entwicklung</title><link>https://kurse.richter.consulting/courses/container/db_container/</link><pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/db_container/</guid><description>&lt;p&gt;Für die erste Nutzung als Entwickler, werden wir ein vorhandenes Beispielprojekt aus dem
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;g fill="#181616"&gt;&lt;path fill-rule="evenodd" d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388c0 26.682 17.303 49.317 41.297 57.303c3.017.56 4.125-1.31 4.125-2.905c0-1.44-.056-6.197-.082-11.243c-16.8 3.653-20.345-7.125-20.345-7.125c-2.747-6.98-6.705-8.836-6.705-8.836c-5.48-3.748.413-3.67.413-3.67c6.063.425 9.257 6.223 9.257 6.223c5.386 9.23 14.127 6.562 17.573 5.02c.542-3.903 2.107-6.568 3.834-8.076c-13.413-1.525-27.514-6.704-27.514-29.843c0-6.593 2.36-11.98 6.223-16.21c-.628-1.52-2.695-7.662.584-15.98c0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033c11.526-7.813 16.59-6.19 16.59-6.19c3.287 8.317 1.22 14.46.593 15.98c3.872 4.23 6.215 9.617 6.215 16.21c0 23.194-14.127 28.3-27.574 29.796c2.167 1.874 4.097 5.55 4.097 11.183c0 8.08-.07 14.583-.07 16.572c0 1.607 1.088 3.49 4.148 2.897c23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z" clip-rule="evenodd"/&gt;&lt;path d="M26.484 91.806c-.133.3-.605.39-1.035.185c-.44-.196-.685-.605-.543-.906c.13-.31.603-.395 1.04-.188c.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28c-.396-.42-.47-.983-.177-1.254c.298-.266.844-.14 1.24.28c.394.426.472.984.17 1.255zm2.382 3.477c-.37.258-.976.017-1.35-.52c-.37-.538-.37-1.183.01-1.44c.373-.258.97-.025 1.35.507c.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23c-.527-.487-.674-1.18-.343-1.544c.336-.366 1.045-.264 1.564.23c.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486c-.683-.207-1.13-.76-.99-1.238c.14-.477.823-.7 1.512-.485c.683.206 1.13.756.988 1.237m4.943.361c.017.498-.563.91-1.28.92c-.723.017-1.308-.387-1.315-.877c0-.503.568-.91 1.29-.924c.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117c-.7.13-1.35-.172-1.44-.653c-.086-.498.422-.997 1.122-1.126c.714-.123 1.354.17 1.444.663zm0 0"/&gt;&lt;/g&gt;&lt;/svg&gt;
&lt;/span&gt;
nehmen. Es liegt im Unterordner &lt;code&gt;blazor-postgres&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Wie der Name schon andeutet, handelt es sich um eine Web-Anwendung mit Blazor. Die Anwendung nutzt zur Datenspeicherung die Datenbank Postgres. Die Datenbank wollen wir als Container ausführen. Das bietet folgende Vorteile:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keine großen Administrator Vorkenntnisse zu Postgres Datenbank notwendig&lt;/li&gt;
&lt;li&gt;Wir können jederzeit entscheiden, welche Version der Datenbank wir nutzen wollen (z.B. kann eine ältere Version der Applikation eine ältere DB Version erfordern - für Fehlerkorrekturen)&lt;/li&gt;
&lt;li&gt;Wir können sehr schnell einen &amp;ldquo;sauberen&amp;rdquo; Zustand der Datenbank erzeugen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="starten-der-applikation"&gt;Starten der Applikation&lt;/h2&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Falls noch nicht geschehen, müssen Sie die
für Ihr Betriebssystem installieren.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Öffnen Sie den Projektordner in dem Editor Ihrer Wahl. Ich nutze dafür VS Code mit der installierten Erweiterung &amp;ldquo;C# DevKit&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Versuchen Sie die App nur zu starten, ohne dass wir aktuell eine passende Datenbank dazu haben.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Da die Anwendung bereits beim Start eine Verbindung zur Datenbank erfordert, scheitert der Start mit einer Fehlermeldung.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Die Starteinstellungen von /Users/eugen/src/container-kurs/blazor-postgres/Properties/launchSettings.json werden verwendet…
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Buildvorgang wird ausgeführt...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fail: Microsoft.EntityFrameworkCore.Database.Connection&lt;span class="o"&gt;[&lt;/span&gt;20004&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; An error occurred using the connection to database &lt;span class="s1"&gt;&amp;#39;devdb&amp;#39;&lt;/span&gt; on server &lt;span class="s1"&gt;&amp;#39;tcp://localhost:5432&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unhandled exception. Npgsql.NpgsqlException &lt;span class="o"&gt;(&lt;/span&gt;0x80004005&lt;span class="o"&gt;)&lt;/span&gt;: Failed to connect to 127.0.0.1:5432
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ---&amp;gt; System.Net.Sockets.SocketException &lt;span class="o"&gt;(&lt;/span&gt;61&lt;span class="o"&gt;)&lt;/span&gt;: Connection refused
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.Internal.NpgsqlConnector.Connect&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlTimeout timeout&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.Internal.NpgsqlConnector.Connect&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlTimeout timeout&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.Internal.NpgsqlConnector.RawOpen&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.Internal.NpgsqlConnector.&amp;lt;Open&amp;gt;g__OpenCore&lt;span class="p"&gt;|&lt;/span&gt;209_0&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlConnector conn, String username, SslMode sslMode, GssEncryptionMode gssEncMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.Internal.NpgsqlConnector.Open&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.PoolingDataSource.OpenNewConnector&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.PoolingDataSource.&amp;lt;Get&amp;gt;g__RentAsync&lt;span class="p"&gt;|&lt;/span&gt;33_0&lt;span class="o"&gt;(&lt;/span&gt;NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.NpgsqlConnection.&amp;lt;Open&amp;gt;g__OpenAsync&lt;span class="p"&gt;|&lt;/span&gt;42_0&lt;span class="o"&gt;(&lt;/span&gt;Boolean async, CancellationToken cancellationToken&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.NpgsqlConnection.Open&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection&lt;span class="o"&gt;(&lt;/span&gt;Boolean errorsExpected&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal&lt;span class="o"&gt;(&lt;/span&gt;Boolean errorsExpected&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open&lt;span class="o"&gt;(&lt;/span&gt;Boolean errorsExpected&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader&lt;span class="o"&gt;(&lt;/span&gt;RelationalCommandParameterObject parameterObject&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.GetAppliedMigrations&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Internal.NpgsqlHistoryRepository.GetAppliedMigrations&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetAppliedMigrations&lt;span class="o"&gt;(&lt;/span&gt;DatabaseFacade databaseFacade&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetPendingMigrations&lt;span class="o"&gt;(&lt;/span&gt;DatabaseFacade databaseFacade&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at BlazorWebAppMovies.Data.SeedData.Initialize&lt;span class="o"&gt;(&lt;/span&gt;IServiceProvider serviceProvider&lt;span class="o"&gt;)&lt;/span&gt; in /Users/eugen/src/container-kurs/blazor-postgres/Data/SeedData.cs:line &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; at Program.&amp;lt;Main&amp;gt;&lt;span class="k"&gt;$(&lt;/span&gt;String&lt;span class="o"&gt;[]&lt;/span&gt; args&lt;span class="k"&gt;)&lt;/span&gt; in /Users/eugen/src/container-kurs/blazor-postgres/Program.cs:line &lt;span class="m"&gt;23&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="start-der-postgres-datenbank"&gt;Start der Postgres Datenbank&lt;/h2&gt;
&lt;p&gt;Damit die Anwendung starten können, müssen wir die Postgres Datenbank starten. Dazu suchen wir auf dem größten Repository für Container Images, dem
von Docker Inc., nach Postgres.&lt;/p&gt;
&lt;h3 id="kategorisierung-in-docker-hub"&gt;Kategorisierung in Docker Hub&lt;/h3&gt;
&lt;p&gt;Die Suche gibt uns sehr viele Ergebnisse zu Postgres, da jeder auf diesem Hub Images veröffentlichen kann. Docker Hub hilft uns ein wenig dabei, das richtige Image herauszufinden, in dem es die Image-Repositories kategorisiert.&lt;/p&gt;
&lt;p&gt;Es gibt sogenannte &amp;ldquo;offizielle&amp;rdquo; Image, die direkt von den Entwicklern der jeweiligen Software zur Verfügung gestellt werden. Nach der Verifizierung, bekommen diese ein Siegel &amp;ldquo;Docker Official Image&amp;rdquo;. Damit sind solche Images am vertrauenswürdigsten. Man erkenn solche Images relativ einfach, an den Namen.&lt;/p&gt;
&lt;p&gt;Die Namen von den offiziellen Images, haben keinen Präfix. Das haben wir bereits bei &lt;code&gt;nginx&lt;/code&gt; gesehen. Auch da bestand der Image-Name nur aus dem Namen der Software. Bei Postgres heißt das Image auch einfach &lt;code&gt;postgres&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Eine weitere Kategorie sind die &amp;ldquo;Verified Publisher&amp;rdquo;. Dabei handelt es sich zwar nicht um die &amp;ldquo;Ersteller&amp;rdquo; der jeweiligen Software, aber um Firmen, die von Docker Inc. validiert und für vertrauenswürdig befunden worden. Es sind of Firmen, die selbst Ihr Geld mit Containern verdienen und optimierte Images für bestimmte Bereiche liefern. Zu den &amp;ldquo;Verified Publisher&amp;rdquo; gehören zum Beispiel&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CircleCI: Ein CI/CD as a Service Anbieter&lt;/li&gt;
&lt;li&gt;Microsoft&lt;/li&gt;
&lt;li&gt;Ubuntu&lt;/li&gt;
&lt;li&gt;Bitnami: Anbieter von VM Images / Container Images&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="aussuchen-der-notwendigen-parameter"&gt;Aussuchen der notwendigen Parameter&lt;/h3&gt;
&lt;p&gt;Wir nutzen für unseren Zweck das offizielle Image von Postgres. Wenn wir in der Suche diesen auswählen, erscheint die Detail-Seite des
. Hier finden wir die Beschreibung, wie das vorhandene Container-Image beim Starten mit Parametern angepasst werden kann. Oft stehen auch Informationen, welche Version, Basis-Images und Architekturen unterstützt werden.&lt;/p&gt;
&lt;p&gt;Das Postgres Repository hat zum Beispiel Images für:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Postgres-Versions: 18, 17, 16, 15, 14, 13, 12&lt;/li&gt;
&lt;li&gt;Architekturen: amd64, arm32v5, arm32v6, arm32v7, arm64v8, i386, mips64le, ppc64le, riscv64, s390x&lt;/li&gt;
&lt;li&gt;Basis-Images
&lt;ul&gt;
&lt;li&gt;alpine: Basiert auf Alpine-Linux&lt;/li&gt;
&lt;li&gt;bullseye: Basiert auf Debian Trixie (13)&lt;/li&gt;
&lt;li&gt;bookworm: Basiert auf Debian Bookworm (12)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Um auf die Datenbank in unserer Anwendung zugreifen zu können, müssen wir folgende Einstellungen für die Datenbank wissen / setzen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Benutzername
&lt;ul&gt;
&lt;li&gt;Kann im offiziellen Image über Umgebungsvariable &lt;code&gt;POSTGRES_USER&lt;/code&gt; gesetzt werden (Standardwert ist &lt;code&gt;postgres&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Passwort
&lt;ul&gt;
&lt;li&gt;Muss im offiziellen Image über Umgebungsvariable &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; gesetzt werden&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Datenbankname
&lt;ul&gt;
&lt;li&gt;Kann im offiziellen Image über Umgebungsvariable &lt;code&gt;POSTGRES_DB&lt;/code&gt; gesetzt werden (Standardwert entspricht dem Benutzernamen)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Die Umgebungsvariablen werden an Docker Runtime mit dem Parameter &lt;code&gt;-e&lt;/code&gt; übergeben (kann auch mehrmals verwendet werden).&lt;/p&gt;
&lt;p&gt;Aus den gesammelten Informationen, können wir nun den geforderten (kürzesten) Aufruf ableiten:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -e &lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;devuser &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;devpassword &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e &lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;devdb &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 5432:5432 -d postgres:18-alpine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-e POSTGRES_USER=devuser&lt;/code&gt;: setzt den Benutzernamen auf &lt;code&gt;devuser&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-e POSTGRES_PASSWORD=devpassword&lt;/code&gt;: setzt das Passwort auf &lt;code&gt;devpassword&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-e POSTGRES_DB=devdb&lt;/code&gt;: setzt die Datenbankname auf &lt;code&gt;devdb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p 5432:5432&lt;/code&gt;: ordnet den Standard Port von Postgres zu demselben Port auf unserem Host zu&lt;/li&gt;
&lt;li&gt;&lt;code&gt;postgres:18-alpine&lt;/code&gt;: startet den Postgres Container mit der Version 18 und dem Alpine-Basis-Image&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/db_container/postgres_container.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Postgres Container in Docker Desktop&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="starten-der-applikation-mit-laufender-datenbank"&gt;Starten der Applikation mit laufender Datenbank&lt;/h3&gt;
&lt;p&gt;Nun läuft die Postgres Datenbank im Hintergrund (in der Version 18), so dass die App auf diese Zugreifen kann. Da wir einige Einstellungen nicht angegeben haben, werden dabei Standardwerte genutzt.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--name&lt;/code&gt;: Wir haben dem Container keinen expliziten Namen gegeben. Aus diesem Fall wird dieser durch die Runtime &amp;ldquo;gewürfelt&amp;rdquo;. Bei meinem ersten Start war der Name &lt;code&gt;funny_austin&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wenn wir jetzt die Applikation starten. In der Ausgabe wird auch die URL Angezeigt, unter der die Applikation erreichbar ist.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Using launch settings from /Users/eugen/src/container-kurs/blazor-postgres/Properties/launchSettings.json...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Building...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fail: Microsoft.EntityFrameworkCore.Database.Command&lt;span class="o"&gt;[&lt;/span&gt;20102&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Failed executing DbCommand &lt;span class="o"&gt;(&lt;/span&gt;10ms&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;=[]&lt;/span&gt;, &lt;span class="nv"&gt;CommandType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Text&amp;#39;&lt;/span&gt;, &lt;span class="nv"&gt;CommandTimeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;30&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SELECT &lt;span class="s2"&gt;&amp;#34;MigrationId&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;ProductVersion&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FROM &lt;span class="s2"&gt;&amp;#34;__EFMigrationsHistory&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ORDER BY &lt;span class="s2"&gt;&amp;#34;MigrationId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fail: Microsoft.EntityFrameworkCore.Database.Command&lt;span class="o"&gt;[&lt;/span&gt;20102&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Failed executing DbCommand &lt;span class="o"&gt;(&lt;/span&gt;1ms&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;=[]&lt;/span&gt;, &lt;span class="nv"&gt;CommandType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Text&amp;#39;&lt;/span&gt;, &lt;span class="nv"&gt;CommandTimeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;30&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SELECT &lt;span class="s2"&gt;&amp;#34;MigrationId&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;ProductVersion&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; FROM &lt;span class="s2"&gt;&amp;#34;__EFMigrationsHistory&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ORDER BY &lt;span class="s2"&gt;&amp;#34;MigrationId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;info: Microsoft.EntityFrameworkCore.Migrations&lt;span class="o"&gt;[&lt;/span&gt;20411&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Acquiring an exclusive lock &lt;span class="k"&gt;for&lt;/span&gt; migration application. See https://aka.ms/efcore-docs-migrations-lock &lt;span class="k"&gt;for&lt;/span&gt; more information &lt;span class="k"&gt;if&lt;/span&gt; this takes too long.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;info: Microsoft.EntityFrameworkCore.Migrations&lt;span class="o"&gt;[&lt;/span&gt;20402&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Applying migration &lt;span class="s1"&gt;&amp;#39;20241206073458_Init&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;info: Microsoft.Hosting.Lifetime&lt;span class="o"&gt;[&lt;/span&gt;14&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Now listening on: http://localhost:5216
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;info: Microsoft.Hosting.Lifetime&lt;span class="o"&gt;[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Application started. Press Ctrl+C to shut down.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Öffnen Sie die Applikation nun unter der ausgegebenen Adresse &lt;code&gt;http://localhost:5216&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/db_container/blazor_app.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Blazor App mit DB Verbindung&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Eine Datei versionieren</title><link>https://kurse.richter.consulting/courses/git/commit/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/commit/</guid><description>&lt;p&gt;Legen wir eine neue Text-Datei an, die wir versionieren möchten.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ touch kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;New-Item&lt;/span&gt; &lt;span class="n"&gt;kapitel_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;kurs&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;LastWriteTime&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="p"&gt;-------------&lt;/span&gt; &lt;span class="p"&gt;------&lt;/span&gt; &lt;span class="p"&gt;----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;-a&lt;/span&gt;&lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="mf"&gt;21.09&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;07&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;32&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt; &lt;span class="n"&gt;kapitel_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wenn wir nun den Status des Repositorys aufrufen, erhalten wir eine ganz andere Meldung.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No commits yet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Untracked files:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (use &amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34; to include in what will be committed)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing added to commit but untracked files present (use &amp;#34;git add&amp;#34; to track)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="datei-zum-staging-bereich-hinzufügen"&gt;Datei zum Staging-Bereich hinzufügen&lt;/h3&gt;
&lt;p&gt;Die Meldung besagt, dass in unserem Ordner eine neue, noch nicht versionierte (&lt;em&gt;untracked&lt;/em&gt;) Datei liegt. Git gibt zugleich auch den Tipp, wie diese Datei unter Versionskontrolle genommen werden kann. Wir folgen einfach dem Tipp und nutzen den &lt;code&gt;add&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; Befehl. Mit &lt;code&gt;status&lt;/code&gt; prüfen wir wieder, welche Auswirkung das auf unser Repository hat.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git add kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;No commits yet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Changes to be committed:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git rm --cached &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to unstage&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; new file: kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun besagt die Meldung, dass wir Änderungen haben, die auf ein Commit warten.&lt;/p&gt;
&lt;h3 id="änderungen-festschreiben"&gt;Änderungen festschreiben&lt;/h3&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt; bei git ist eine Aktion, mit der der aktuelle Stand als Version gespeichert wird. Zu einem Commit müssen die betroffenen Dateien vorgemerkt werden. Dieses Vormerken wird auch &lt;strong&gt;Staging&lt;/strong&gt; genannt.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Nun schreiben wir die Version mit einen &lt;code&gt;commit&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; endgültig fest. Dabei ist es bei git auch immer notwendig eine Nachricht mitzugeben (Parameter &lt;code&gt;-m&lt;/code&gt;), die die aktuelle Version beschreibt. Eine gute Dokumentation, wie eine Commit-Nachricht aussehen könnte, finden Sie unter
.&lt;/p&gt;
&lt;p&gt;Wird die Nachricht (Message) nicht direkt mit angegeben, startet git automatisch vorkonfigurierten Text-Editor, um die Nachricht in diesem einzugeben. Das ist sehr praktisch, wenn man mehrzeilige Nachrichten an die Version anhängen möchte.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git commit -m &lt;span class="s2"&gt;&amp;#34;feat: Start des ersten Kapitels&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*** Please tell me who you are.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; git config --global user.email &lt;span class="s2"&gt;&amp;#34;you@example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; git config --global user.name &lt;span class="s2"&gt;&amp;#34;Your Name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to &lt;span class="nb"&gt;set&lt;/span&gt; your account&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s default identity.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Omit --global to &lt;span class="nb"&gt;set&lt;/span&gt; the identity only in this repository.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fatal: empty ident name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &amp;lt;kurse@pc.localdomain&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt; not allowed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="benutzer-in-git-einrichten"&gt;Benutzer in git einrichten&lt;/h3&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-orange-100 dark:bg-orange-900 border-orange-500"
data-callout="warning"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-orange-600 dark:text-orange-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0zM12 15.75h.007v.008H12z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Warnung&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Nutzten Sie git zum ersten Mal, erscheint eine Fehlermeldung, dass git uns noch nicht kennt. Git benötigt immer den Namen und die E-Mail-Adresse des Benutzers, um diese in der Versionshistorie zu nutzen. In der Fehlermeldung steht auch, wie der Fehler korrigiert werden kann.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git config --global user.email &lt;span class="s2"&gt;&amp;#34;kurse@richter.consulting&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git config --global user.name &lt;span class="s2"&gt;&amp;#34;Eugen [WebDucer] Richter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git commit -m &lt;span class="s2"&gt;&amp;#34;feat: Start des ersten Kapitels&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;main &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; e12fb6d&lt;span class="o"&gt;]&lt;/span&gt; feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;0&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="m"&gt;0&lt;/span&gt; deletions&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Jetzt haben wir unseren ersten Commit mit git erstellt. Mit &lt;code&gt;git status&lt;/code&gt; kann nachgeprüft werden, ob das Repository nun wieder in einen &lt;em&gt;sauberen&lt;/em&gt; Zustand ist.&lt;/p&gt;
&lt;h3 id="allgemeiner-ablauf"&gt;Allgemeiner Ablauf&lt;/h3&gt;
&lt;p&gt;Der allgemeine Ablauf beim Arbeiten mit git sieht damit wie folgt aus:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Anlegen oder ändern der Dateien, die versioniert werden sollen.&lt;/li&gt;
&lt;li&gt;Hinzufügen der neuen oder geänderten Dateien über &lt;code&gt;git add dateiA dateiB&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Festschreiben der neuen Version mit &lt;code&gt;git commit -m &amp;quot;Warum wurde etwas geändert&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Orchestrierung mit Docker Compose</title><link>https://kurse.richter.consulting/courses/container/compose/</link><pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/compose/</guid><description>&lt;p&gt;Bereits in unserem kleinen Beispiel bräuchten wir normalerweise mehr als einen Container. Es wäre schön, wenn wir neben der Datenbank, auch eine Web-basierte UI für die Verwaltung der Datenbank zur Hand hätten (gibt es ja fast für alle Datenbanken). Damit müssten wir nicht für jede Datenbank auch noch ein Tool installieren, mit dem man die Daten anschauen kann.&lt;/p&gt;
&lt;p&gt;Aber bereits 2 Container bringen eine gewisse Komplexität. Zum Beispiel müssen wir die UI für die Datenbank erst starten, wenn die Datenbank bereits hochgefahren und verfügbar ist. Mit mehr Containern (z.B. Redis für Caching, Prometheus für Monitoring, Logging und Tracing, Grafana für Visualisierung dieser Daten, usw.). Alle haben eigene Voraussetzungen, Abhängigkeiten usw.&lt;/p&gt;
&lt;p&gt;Wäre es nicht schön, so eine &amp;ldquo;Laufzeitumgebung&amp;rdquo; ein Mal zu definieren und immer wieder (sauber) ausführen zu können? Eventuell diese Konfiguration direkt mit dem Projekt auch mit den Kollegen teilen?&lt;/p&gt;
&lt;p&gt;So eine Orchestrierung von unterschiedlichen Containern können wir mit &amp;ldquo;Docker Compose&amp;rdquo; umsetzten. Das ist praktisch ein kleiner Bruder von Kubernetes, das für die professionelle, hoch skalierbare, Orchestrierungen gedacht ist.&lt;/p&gt;
&lt;h2 id="orchestrierung-mit-docker-compose"&gt;Orchestrierung mit Docker Compose&lt;/h2&gt;
&lt;p&gt;Die Container, die mit &amp;ldquo;Docker Compose&amp;rdquo; orchestriert werden sollen, werden in einer &lt;abbr title="YAML Ain’t Markup Language"&gt;&lt;code&gt;YAML&lt;/code&gt;&lt;/abbr&gt; Datei definiert und konfiguriert. Die CLI dafür wird mit &amp;ldquo;Docker Desktop&amp;rdquo; mitgeliefert. Ist diese auf Ihrem System nicht installiert, können Sie den Installationsanweisungen von der offiziellen
folgen.&lt;/p&gt;
&lt;p&gt;Die Datei wird standardmäßig &lt;code&gt;docker-compose.yml&lt;/code&gt; genannt und befindet sich in dem gleichen Verzeichnis wie das Projekt. Hier ist der Grundaufbau der Datei:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Liste der Services / Container&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Datenbank Container&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Container image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;postgres:18-alpine&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Umgebungsvariablen&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;super-secret-password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Port Mapping&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;5432:5432&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dbAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Container image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;dpage/pgadmin4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Umgebungsvariablen&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PGADMIN_DEFAULT_EMAIL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;admin@example.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PGADMIN_DEFAULT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;super-secret-password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Port Mapping&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8080:80&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Konfiguration enthält min. ein Service (Container) das gestartet werden soll.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In der Zeile &lt;mark&gt;4&lt;/mark&gt; starten wir die Konfiguration von Postgres Datenbank. Der Service enthält den Namen &lt;code&gt;db&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;6&lt;/mark&gt; definiert das Image, das verwendet wird (Postgres in diesem Fall).&lt;/li&gt;
&lt;li&gt;In der Zeile &lt;mark&gt;8&lt;/mark&gt; definieren wir die Umgebungsvariablen, die beim Starten des Containers gesetzt werden sollen. In diesem Fall &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; wird auf &lt;code&gt;super-secret-password&lt;/code&gt; gesetzt.&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;10&lt;/mark&gt; definiert das Port Mapping, mit dem Containerport 5432 mit dem Hostport 5432 verbunden wird.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der zweite Service ist eine Admin-UI für Postgres. Sie wird mit dem Namen &lt;code&gt;dbAdmin&lt;/code&gt; gestartet und verwendet die Image &lt;code&gt;dpage/pgadmin4&lt;/code&gt;. Die Umgebungsvariablen werden ebenfalls gesetzt, um den Benutzername und das Passwort für die Admin-UI zu definieren.&lt;/p&gt;
&lt;p&gt;Da bei der Definition des Images for &lt;code&gt;dbAdmin&lt;/code&gt; keine Version angegeben wird (kein &lt;code&gt;:tagName&lt;/code&gt; am Ende), wird der Tag automatisch auf &lt;code&gt;latest&lt;/code&gt; gesetzt (Docker Konvention).&lt;/p&gt;
&lt;h2 id="starten-der-orchestrierten-container"&gt;Starten der Orchestrierten Container&lt;/h2&gt;
&lt;p&gt;Um nun alle konfigurierten Services zu starten, nutzen wir die &amp;ldquo;Docker Compose&amp;rdquo; CLI. Die Aufrufe müssen in dem Ordner erfolgen, in dem die &lt;code&gt;docker-compose.yml&lt;/code&gt; Datei liegt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/compose/compose_up.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Gestarteten Container über Compose&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Unter &lt;code&gt;http://localhost:8080&lt;/code&gt; können Sie sich nun mit den Zugangsdaten (aus der Konfiguration) anmelden und eine Verbindung zur Datenbank herstellen (Hostname &lt;code&gt;db&lt;/code&gt;, wie der Service Name).&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/compose/pgadmin_ui.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Postgres Admin Web-UI&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="anpassung-der-orchestrierung-an-die-applikation"&gt;Anpassung der Orchestrierung an die Applikation&lt;/h2&gt;
&lt;p&gt;Damit passt die aktuelle minimalistische Konfiguration aber noch nicht zu unseren Anforderungen der App.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wir haben vorgegebene Anmeldedaten für die Datenbank&lt;/li&gt;
&lt;li&gt;Wir haben einem, vom Standard abweichenden Datenbanknamen&lt;/li&gt;
&lt;li&gt;Es wäre gut, wenn pgAdmin bereits die Verbindung zu unseren Datenbank hätte, ohne dass wir es jedes Mal nach Neustart eingeben müssten&lt;/li&gt;
&lt;li&gt;pgAdmin sollte erst starten, wenn die Datenbank einsatzbereit ist (&amp;ldquo;health check&amp;rdquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Die Konfiguration der Datenbank können wir leicht anpassen. Die entsprechenden Umgebungsvariablen-Werte kennen wir bereits aus dem direkten Start mit Docker.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;devuser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;devpassword&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;devdb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Für die Prüfung, ob der Container wirklich einsatzbereit ist, müssen wir einen &amp;ldquo;health check&amp;rdquo; umsetzen. Dieser ist immer abhängig vom Service. Für unsere Postgres Datenbank könnte dieser wie folgt aussehen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD-SHELL&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pg_isready -U devuser -d devdb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;2s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;start_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;5s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;30s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Zeile &lt;mark&gt;3&lt;/mark&gt; startet die Definition für &amp;ldquo;health check&amp;rdquo; (
)&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;4&lt;/mark&gt; beschreibt den Befehl, mit dem die &amp;ldquo;Bereitschaft&amp;rdquo; geprüft werden kann. Bei Postgres können wir dazu &lt;code&gt;pg_isready&lt;/code&gt; Tool nutzen. (
)&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;5&lt;/mark&gt; gibt an, in welchen Zeitabständen der Check durchgeführt wird, nach dem Ablauf der &lt;code&gt;start_period&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;6&lt;/mark&gt; gibt an die Anzahl der Versuche, bis der Start als fehlerhaft markiert wird&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;7&lt;/mark&gt; gibt die üblich Startzeit an. In dieser Zeit wir der Container zwar getestet, die Fehler zählen in dieser Zeit aber nicht zu Wiederholungen.&lt;/li&gt;
&lt;li&gt;Zeile &lt;mark&gt;8&lt;/mark&gt; gibt an, wie lange ein Check max. dauern soll, bis der als fehlerhaft erkannt wird&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In pgAdmin können wir nun die Datenbank als Abhängigkeit eintragen, so dass der Container erst dann startet, wenn die
(auf Verbindungsversuche antwortet) ist.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dbAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_healthy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun fehlt uns nur noch die Konfiguration von pgAdmin, so dass unsere Datenbank da bereits &amp;ldquo;hinterlegt&amp;rdquo; ist. Dazu müssen wir (leider) die
von pgAdmin genauer ansehen.&lt;/p&gt;
&lt;p&gt;Damit wir uns nicht jedes Mal anmelden müssen (wir sind ja auf unseren eigenen Rechner und betreiben keinen Server), können wir pgAdmin ich einen &amp;ldquo;nicht&amp;rdquo; Server Modus starten&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dbAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;False&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PGADMIN_CONFIG_SERVER_MODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;False&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PGADMIN_CONFIG_SERVER_MODE&lt;/code&gt; schaltet pgAdmin in single User Mode, so dass wir uns nicht mehr anmelden müssen&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED&lt;/code&gt; erlaubt uns im nächsten Schritt die Konfiguration des Servers durchzureichen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Im letzten Schritt legen wir eine Konfigurationsdatei für die Serverkonfiguration, die wir an pgAdmin durchreichen werden. Diese können wir indirekt für uns erstellen lassen, in dem wir den Server zuerst in pgAdmin konfigurieren und diese Konfiguration dann als JSON-Datei exportieren. Die exportierte Datei muss dann über Docker Desktop aus dem Container exportiert werden.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Servers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;DB&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Group&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Servers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Host&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Port&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;MaintenanceDB&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;devdb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Username&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;devuser&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;PasswordExecCommand&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;echo \u0027devpassword\u0027&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Zeile &lt;mark&gt;10&lt;/mark&gt; übergeben wir das Passwort über ein &lt;code&gt;echo&lt;/code&gt; Befehl, da die Konfiguration die Speicherung von unverschlüsselten Passwörtern nicht erlaubt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dbAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Datei und Orner Mappings&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./db_server.json:/pgadmin4/servers.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Zeile &lt;mark&gt;5&lt;/mark&gt; Mappen wir unsere Konfigurationsdatei &lt;code&gt;servers.json&lt;/code&gt; in den Container hinein. pgAdmin erwartet die Serverkonfiguration im Ordner &lt;code&gt;/pgadmin4&lt;/code&gt; mit dem Dateinamen &lt;code&gt;servers.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nun können wir unsere Konfiguration starten. In der Kommandozeile sehen wir auch, dass pgAdmin erst starten, wenn Postgres in den &amp;ldquo;healthy&amp;rdquo; Status wechselt. Wenn wir nun die pgAdmin Web-Oberfläche öffnen, gelangen wir direkt, ohne Anmeldung, hinein. Auch der Postgres Server ist für uns bereits konfiguriert.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/compose/pgadmin_no_login.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;pgAdmin ohne Anmeldung mit Serverkonfiguration&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Historie anzeigen lassen</title><link>https://kurse.richter.consulting/courses/git/history/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/history/</guid><description>&lt;p&gt;Die Historie eines Repositorys kann über den Befehl &lt;code&gt;log&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; angesehen werden. Dieser gibt eine sehr ausführliche Information über alle gemachten Commits. Der Befehl hat viele Parameter und kann sehr gut angepasst werden (was wir später noch nutzen werden).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;commit e12fb6dc6e0b69af839d95efff837ecebf7e443f &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Author: Eugen &lt;span class="o"&gt;[&lt;/span&gt;WebDucer&lt;span class="o"&gt;]&lt;/span&gt; Richter &amp;lt;kurse@richter.consulting&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Tue Sep &lt;span class="m"&gt;21&lt;/span&gt; 08:06:48 &lt;span class="m"&gt;2021&lt;/span&gt; +0200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="verkürzte-anzeige-der-historie"&gt;Verkürzte Anzeige der Historie&lt;/h3&gt;
&lt;p&gt;Wenn die Anzahl der Commits steigt, wird die &lt;em&gt;ausführliche&lt;/em&gt; Ausgabe der Historie sehr unübersichtlich. Mit dem Parameter &lt;code&gt;--pretty=oneline&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; kann die Ausgabe pro Commit auf eine Zeile reduziert werden.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git log --pretty&lt;span class="o"&gt;=&lt;/span&gt;oneline
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e12fb6dc6e0b69af839d95efff837ecebf7e443f &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit den Parametern &lt;code&gt;--oneline --decorate&lt;/code&gt; wird die Ausgabe noch kürzer. Dabei wird der Commit-Hash auf 7 Zeichen gekürzt (statt 32). Die Kürzung ist für die meisten Repositorys unproblematisch und weiterhin eindeutig.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git log --oneline --decorate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e12fb6d &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="aliases"&gt;Aliases&lt;/h3&gt;
&lt;p&gt;Da man die langen Befehle mit vielen Parametern nicht jedes Mal aus dem Gedächtnis herauskramen will, bietet git die Möglichkeit, diese mit einem Alias (alternativen Namen) zu versehen. Wir vergeben für unsere Log-Anzeige ein Alias&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;code&gt;pl&lt;/code&gt; (für pretty log).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git config --global alias.pl &lt;span class="s1"&gt;&amp;#39;log --graph --oneline --decorate --all&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das Alias wir dabei in der globalen (&lt;code&gt;--global&lt;/code&gt;) Konfiguration von git gespeichert.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;log&lt;/code&gt;: git Befehl, in unserem Fall log&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--graph&lt;/code&gt;: Darstellung des Logs als Graph (dazu später mehr, wenn wir mehr als ein branch haben)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--oneline&lt;/code&gt;: Einzeilige Darstellung&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--decorate&lt;/code&gt;: &lt;em&gt;Hübsche&lt;/em&gt; Darstellung der Zeile&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--all&lt;/code&gt;: Alle Branches anzeigen, nicht nur das aktuelle (später mehr dazu)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nun können wir mit dem einfachen &lt;code&gt;git pl&lt;/code&gt; das Log mit vielen Parametern einfach aufrufen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Eigene App in Container verpacken</title><link>https://kurse.richter.consulting/courses/container/build_image/</link><pubDate>Sun, 08 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/build_image/</guid><description>&lt;p&gt;Wenn man eine Zeit lang die Container für sich arbeiten lässt und diese nutzt, kommt irgendwann der Gedanke, auch eigene Applikation in einen Container zu verpacken und auszuliefern. Das wollen wir am Beispiel unser Blazor Beispielprojektes ein Mal durchspielen.&lt;/p&gt;
&lt;p&gt;Um ein Image zu erstellen, benötigen wir eine Bauanleitung. Diese wird in Form eines sogenannten Docker-Files definiert. Die Datei beschreibt Schritt für Schritt, was wir am Basissystem machen müssen, um unsere Applikation zu veröffentlichen. Dazu kommen noch einige Konfigurationsangaben, wie Port oder verfügbare Umgebungsvariablen.&lt;/p&gt;
&lt;h2 id="anpassbarkeit-des-images"&gt;Anpassbarkeit des Images&lt;/h2&gt;
&lt;p&gt;Als erstes müssen wir überlegen, welche Möglichkeiten wir dem &amp;ldquo;Nutzer&amp;rdquo; des Images zur Verfügung stellen müssen (und wollen). Da es sich um eine Web-Anwendung handelt, sollten wir mindestens den Port für den Web-Server freigeben, so dass die Anwendung auch von Außen ansprechbar ist.&lt;/p&gt;
&lt;p&gt;Da unsere Anwendung eine Datenbankverbindung benötigt, sollten wir erlauben diese zu konfigurieren. Hier könnten wir entweder direkt den kompletten &amp;ldquo;Connection String&amp;rdquo; empfangen, oder diesen in Teilen konfigurierbar machen.&lt;/p&gt;
&lt;h2 id="auswahl-des-basis-images"&gt;Auswahl des Basis-Images&lt;/h2&gt;
&lt;p&gt;Unsere Anwendung basiert auf der .Net Laufzeitumgebung und benötigt das ASP .Net Core Framework. Im ersten Schritt wollen wir auch, dass die App in dem Container (einfachheitshalber) direkt gebaut wird. Die Applikation nutzt .Net 10 als Version der Laufzeitumgebung. Eine Liste mit verfügbaren (offiziellen) Repositories für .Net finden wir
.&lt;/p&gt;
&lt;p&gt;Für unsere Zwecke werden wir das &amp;ldquo;sdk&amp;rdquo; Basis-Image nutzen.&lt;/p&gt;
&lt;h2 id="dockerfile"&gt;Dockerfile&lt;/h2&gt;
&lt;p&gt;Die Datei
ist eine einfache Textdatei, die einem Schema folgt. Jede neue Zeile (Anweisung) erzeugt dabei eine neue Schicht im Dateisystem des fertigen Images. Die Datei fängt immer mit einer
Anweisung, gefolgt von dem Basis-Image, auf dem wir unsere Applikation aufbauen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Basis-Image .Net 10 SDK&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="kopieren-des-projektes"&gt;Kopieren des Projektes&lt;/h3&gt;
&lt;p&gt;Im nächsten Schritt (nächste Zeile) legen wir das Verzeichnis (
) an, in dem wir &amp;ldquo;arbeiten&amp;rdquo; wollen. Und kopieren (
) den aktuellen Inhalt des Projektes in dieses Verzeichnis.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verzeichnis für die App&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Kopiere das Projekt in das Arbeitsverzeichnis&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="bauen-des-projektes"&gt;Bauen des Projektes&lt;/h3&gt;
&lt;p&gt;Nun folgen die Standardschritte von &lt;code&gt;dotnet&lt;/code&gt; um eine Applikation für die Veröffentlichung zu bauen. Dieser Schritt ist spezifisch für die jeweilige Sprache / Framework (und unabhängig von Docker / Containern). Die Befehle werden durch die
Anweisung ausgeführt. Jede Zeile erzeugt, wie erwähnt, eine neue Schicht im Dateisystem.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Wiederherstellen der Abhängigkeiten&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet resore&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Veröffentlichen der App in das Verzeichnis /app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet publish BlazorWebAppMovies.csproj -c Release -o /app&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="konfiguration-des-ports-und-datenbankverbindung"&gt;Konfiguration des Ports und Datenbankverbindung&lt;/h3&gt;
&lt;p&gt;Da wir eine Web-Anwendung haben, die eine Datenbank benötigt, sollen wir diese parametrisieren. Für das Arbeiten einer Web-Anwendung im Container ist es wichtig, dass wir ein Port zur Verfügung stellen, über den die Applikation erreichbar ist. In dem SDK Package ist das Port für Webanwendungen auf &lt;code&gt;8080&lt;/code&gt; gesetzt (kann über die Umgebungsvariable &lt;code&gt;ASPNETCORE_HTTP_PORTS&lt;/code&gt; angepasst werden).&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/build_image/sdk_container_port.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Standard port in SDK image&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Der Port wird über die Anweisung
angegeben und kann neben dem Port selbst auch dar Protokoll enthalten.&lt;/p&gt;
&lt;p&gt;Unsere Applikation ist auch von einer Datenbank abhängig. Wir müssen den &amp;ldquo;Connection String&amp;rdquo; mit übergeben, damit der Container sich mit der Datenbank verbinden kann. In .Net werden die Einstellungen in &lt;code&gt;appsettings.json&lt;/code&gt; Datei (&lt;abbr title="JavaScript Object Notation"&gt;JSON&lt;/abbr&gt; Format) gespeichert. Will man diese Einstellungen mit Umgebungsvariablen überschreiben, werden die Verschachtlungen über ein &lt;code&gt;__&lt;/code&gt; (doppeltes Unterstrich) abgebildet. Aus aktuell &lt;code&gt;{ &amp;quot;ConnectionStrings&amp;quot;: { &amp;quot;BlazorWebAppMoviesContext&amp;quot;: &amp;quot;&amp;quot; } }&lt;/code&gt; wird so &lt;code&gt;ConnectionStrings__BlazorWebAppMoviesContext&lt;/code&gt;. Da Umgebungsvariablen oft in Großbuchstaben geschrieben werden (und für .Net Konfigurationen es irrelevant ist), werden wir es als &lt;code&gt;CONNECTIONSTRINGS__BLAZORWEBAPPMOVIESCONTEXT&lt;/code&gt; schreiben.&lt;/p&gt;
&lt;p&gt;Die Umgebungsvariablen werden in Dockerfile mit der Anweisung
definiert. Schlüssel und Wert werden über &lt;code&gt;=&lt;/code&gt; getrennt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Neues Arbeitsverzeichnis&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Datenbank Connection string&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; &lt;span class="nv"&gt;CONNECTIONSTRINGS__BLAZORWEBAPPMOVIESCONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Port für Webserver&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="starten-der-anwendung"&gt;Starten der Anwendung&lt;/h3&gt;
&lt;p&gt;Der letzte Schritt ist nun die Anweisung, um die Anwendung in dem Container zu startet. Da wir die Applikation nicht manuell innerhalb des Containers starten wollen, sollte dies direkt beim &amp;ldquo;Instanziieren&amp;rdquo; des Containers geschehen.&lt;/p&gt;
&lt;p&gt;Die Anwendung selbst wird über die
Anweisung ausgeführt. Die Anweisung nimmt eine Liste an Parametern entgegen. Die Applikationen in .Net startet man mit dem &lt;code&gt;dotnet&lt;/code&gt; Befehl und dem Applikationsnamen (entspricht dem Projektnamen).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Start der .Net Anwendung&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;BlazorWebAppMovies.dll&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="image-bauen"&gt;Image bauen&lt;/h2&gt;
&lt;p&gt;Im letzten Schritt können wir nun die &amp;ldquo;Bauanleitung&amp;rdquo; dazu nutzen unser erstes Image mit unserer Anwendung zu bauen. Dazu dient der Befehl
.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker build -t blazor-movies:from-sdk .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-t&lt;/code&gt;: Tag des Images, also der Image-Name + Version. In unserem Fall vergeben wir den Namen &lt;code&gt;blazor-movies&lt;/code&gt;. Da wir einige Images bauen werden und diese miteinander vergleichen möchten, vergeben wir eine sprechenden Versionsnamen. Aktuelle Buildanleitung basiert auf dem SDK-Image. Der Versionsname ist bei uns deshalb &lt;code&gt;from-sdk&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt;: Das &lt;code&gt;.&lt;/code&gt; hinter dem Tab bestimmt den
(Pfad). Der Build-Context steht beim Bauen zur Verfügung (wie bei uns der Quellcode der Anwendung). &lt;code&gt;.&lt;/code&gt; bedeutet dabei, der aktuelle Ordner.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Sie können die Datei der Bauanleitung auch anders benennen als &lt;code&gt;Dockerfile&lt;/code&gt;, müssen dann aber beim Bauen den Dateinamen als Parameter (&lt;code&gt;-f&lt;/code&gt;) mit übergeben. Wenn Sie zum Beispiel die Datei &lt;code&gt;Dockerfile.dev&lt;/code&gt; nennen würden, würde der Baubefehl wie folgt aussehen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker build -t blazor-movies:dev -f Dockerfile.dev .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="finale-version"&gt;Finale Version&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verzeichnis für die App&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Kopiere das Projekt in das Arbeitsverzeichnis&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Wiederherstellen der Abhängigkeiten&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet restore&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Veröffentlichen der App in das Verzeichnis /app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet publish BlazorWebAppMovies.csproj -c Release -o /app&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Arbeitsverzeichnis für Ausführung&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Datenbank Connection string&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; &lt;span class="nv"&gt;CONNECTIONSTRINGS__BLAZORWEBAPPMOVIESCONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Port für Webserver&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Start der .Net Anwendung&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;BlazorWebAppMovies.dll&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/build_image/sdk_image.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Unser Image in Docker Desktop&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Ausnahmen für Versionierung</title><link>https://kurse.richter.consulting/courses/git/ignores/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/ignores/</guid><description>&lt;p&gt;Es kommt oft vor, das in dem Ordner nicht nur Dateien liegen, die versioniert werden sollen, sondern auch andere (eventuell temporäre) Dateien. Bei der Software-Entwicklung sind es zum Beispiel die kompilierten Binärdateien, oder auch sehr viele temporäre. Auch Office hinterlegt oft temporäre Dateien, wenn man das Original bearbeitet.&lt;/p&gt;
&lt;p&gt;Legen wir eine temporäre Datei an, die wir nicht in der Versionsverwaltung haben wollen, zum Beispiel mit dem Namen &lt;code&gt;kapitel_1.~&lt;/code&gt; und &lt;code&gt;kapitel_1.bak&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ touch kapitel_1.~ kapitel_1.bak
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kapitel_1.bak kapitel_1.txt kapitel_1.~
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;New-Item&lt;/span&gt; &lt;span class="n"&gt;-ItemType&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="n"&gt;-Path&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kapitel_1.~&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;kapitel_1.bak&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;kurs&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;LastWriteTime&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="p"&gt;-------------&lt;/span&gt; &lt;span class="p"&gt;------&lt;/span&gt; &lt;span class="p"&gt;----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;-a&lt;/span&gt;&lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="mf"&gt;28.10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;08&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;50&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt; &lt;span class="n"&gt;kapitel_1&lt;/span&gt;&lt;span class="p"&gt;.~&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;-a&lt;/span&gt;&lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="mf"&gt;28.10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;08&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;50&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt; &lt;span class="n"&gt;kapitel_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;bak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wenn wir jetzt &lt;code&gt;git status&lt;/code&gt; aufrufen, sehen wir zwei noch nicht versionierte Dateien. Das wollen wir eigentlich nicht sehen, da diese Dateien uns nicht interessieren.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Untracked files:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to include in what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_1.bak
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_1.~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing added to commit but untracked files present &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="globale-ausnahmen-betriebssystem"&gt;Globale Ausnahmen (Betriebssystem)&lt;/h2&gt;
&lt;p&gt;Git bietet für solche Dateien zwei Orte, in denen die Ausnahmen definiert werden können. Wir können die Ausnahmen global (auf Benutzerebene) definieren, oder pro Repository.&lt;/p&gt;
&lt;p&gt;Um eine neue Ausnahmedatei für den Benutzer anzulegen, geben Sie Folgendes ein:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git config --global core.excludesfile ~/.gitignore_global
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ touch ~/.gitignore_global
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Winfows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-global&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;excludesfile&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$env:USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.gitignore_global&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;New-Item&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$env:USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.gitignore_global&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;kurs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;LastWriteTime&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="p"&gt;-------------&lt;/span&gt; &lt;span class="p"&gt;------&lt;/span&gt; &lt;span class="p"&gt;----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;-a&lt;/span&gt;&lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="mf"&gt;11.11&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;19&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;47&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;gitignore_global&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun kann in die betreffende Datei &lt;code&gt;.gitignore_global&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; die Liste der globalen Ausnahmen gepflegt werden. Fügen Sie in unserem Fall einfach Folgendes als erste Zeilen in die Datei ein:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ignore global backup files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;*.bak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Zeilen, die mit &lt;code&gt;#&lt;/code&gt; Anfangen, werden als Kommentare ausgewertet.&lt;/p&gt;
&lt;p&gt;Eine sehr gute Übersicht über übliche Ausnahmen liefert die Seite
. Im Verzeichnis &lt;code&gt;Global&lt;/code&gt; sind dabei die globalen Ausnahmen für unterschiedliche Betriebssysteme (z.B. bei macOS ist es üblich die Datei &lt;code&gt;.DS_Store&lt;/code&gt; auszufiltern, oder unter Windows &lt;code&gt;Thumbs.db&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Pro Zeile in der Datei wird eine Ausnahme definiert, die auch Globings (Platzhalter) erlaubt.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*&lt;/code&gt;: Beliebiges Zeichen, beliebige Anzahl&lt;/li&gt;
&lt;li&gt;&lt;code&gt;**&lt;/code&gt;: Beliebige Unterverzeichnisse&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&lt;/code&gt;: Ein Zeichen&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[Aa]&lt;/code&gt;: Regex für kleines/großes A&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!abc&lt;/code&gt;: Mit &lt;code&gt;!&lt;/code&gt; kann die Ausnahme umgekehrt werden (zum Beispiel alles im Ordner &lt;code&gt;XYZ&lt;/code&gt; nicht versionieren, aber die Datei &lt;code&gt;abc.md&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nach dem Hinzufügen der oberen Ausnahme können wir wieder mit &lt;code&gt;git status&lt;/code&gt; unsere Bemühungen überprüfen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Untracked files:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to include in what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_1.~
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing added to commit but untracked files present &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun wir die Datei &lt;code&gt;kapitel_1.bak&lt;/code&gt; nicht mehr angezeigt.&lt;/p&gt;
&lt;h2 id="ausnahmen-im-repository"&gt;Ausnahmen im Repository&lt;/h2&gt;
&lt;p&gt;Die Ausnahmen für ein konkretes Repository werden in der Datei &lt;code&gt;.gitignore&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; definiert. Meistens wird diese Datei in die Versionsverwaltung aufgenommen, da diese Ausnahmen das konkrete Projekt betreffen und für alle Beteiligten relevant sind.&lt;/p&gt;
&lt;p&gt;Die Datei &lt;code&gt;.gitignore&lt;/code&gt; gilt dabei für das aktuelle Verzeichnis und alle Unterverzeichnisse. Unterverzeichnisse können dabei eigene Ausnahmen in eigenen &lt;code&gt;.gitignore&lt;/code&gt; Dateien definieren, die die Ausnahmen aus den übergeordneten Verzeichnissen ergänzen.&lt;/p&gt;
&lt;p&gt;Legen Sie nun die &lt;code&gt;.gitignore&lt;/code&gt; Datei im Wurzelverzeichnis von unserem Repository.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux / macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ touch .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;New-Item&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;gitignore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;C:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;kurs&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;repo_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="n"&gt;LastWriteTime&lt;/span&gt; &lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;----&lt;/span&gt; &lt;span class="p"&gt;-------------&lt;/span&gt; &lt;span class="p"&gt;------&lt;/span&gt; &lt;span class="p"&gt;----&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;-a&lt;/span&gt;&lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="mf"&gt;11.11&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;2021&lt;/span&gt; &lt;span class="mf"&gt;19&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;53&lt;/span&gt; &lt;span class="mf"&gt;0&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;gitignore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fügen Sie in die neue Ausnahmedatei folgende Zeilen, um unsere &lt;code&gt;.~&lt;/code&gt; Datei von der Versionsverwaltung auszuschließen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Exclude temporal files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;*.~&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit &lt;code&gt;git status&lt;/code&gt; sehen wir nun, dass auch die &lt;code&gt;.~&lt;/code&gt; Datei in der Auflistung nicht mehr auftaucht, dafür aber unsere neue &lt;code&gt;.gitignore&lt;/code&gt; Ausnahmedatei. Diese sollen wir versionieren.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Untracked files:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to include in what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing added to commit but untracked files present &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git add .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git commit -m &lt;span class="s2"&gt;&amp;#34;Add repo ignore file for temp files&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;main c3b4e8b&lt;span class="o"&gt;]&lt;/span&gt; Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;1&lt;/span&gt; insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Auf der bereits erwähnten
finden Sie eine Sammlung von Ausnahmedateien für unterschiedliche Projekte (Programmiersprachen / Tools). Sie müssen damit die Ausnahmelisten nicht selbst erstellen, sondern von dieser Seite die vorhandenen als Ausgangsbasis für eigene Projekte nutzen.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Multi Stage Builds</title><link>https://kurse.richter.consulting/courses/container/multi_stage/</link><pubDate>Sun, 08 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/multi_stage/</guid><description>&lt;p&gt;Wenn wir die Größe unseres Images in Docker Desktop anschauen (oder mit dem Docker-Befehl
auf der Kommandozeile), sehen wir, dass die Größe gewaltig ist. Auf meinem Rechner ist das Image 2.6 GB groß. Warum ist es so?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE ID DISK USAGE CONTENT SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blazor-movies:from-sdk e561bfaae17f 2.55GB 758MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcr.microsoft.com/dotnet/sdk:10.0 d1823fecac36 1.29GB 318MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ursachen-für-große-images"&gt;Ursachen für große Images&lt;/h2&gt;
&lt;p&gt;Schauen wir uns die Ursachen für die Größe an.&lt;/p&gt;
&lt;h3 id="größe-des-basisimages"&gt;Größe des Basisimages&lt;/h3&gt;
&lt;p&gt;Einen großen Einfluss auf die endgültige Größe hat natürlich das Basisimage. Unsere App kommt ja immer &amp;ldquo;on Top&amp;rdquo; von diesem Basisimage. Aktuell nutzen wir SDK-Image als Basis, das alleine bereits 1.3 GB groß ist. Das SDK-Image bringt alles mit, was notwendig ist, um eine dotnet Applikation ausführen, aber auch bauen zu können.&lt;/p&gt;
&lt;h3 id="daten-im-image"&gt;Daten im Image&lt;/h3&gt;
&lt;p&gt;Da wir die Applikation in dem Image selbst bauen, hat dieser nicht nur die fertige App, sondern auch noch:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quellcode, den wir kopiert haben, um die Applikation bauen zu können&lt;/li&gt;
&lt;li&gt;Eventuelle &amp;ldquo;Zwischen-Dateien&amp;rdquo;, die bei einem Build-Prozess entstehen, aber nicht in die finale App reinfließen (bei dotnet z.B. die &lt;code&gt;obj&lt;/code&gt; und &lt;code&gt;bin&lt;/code&gt; Ordner)&lt;/li&gt;
&lt;li&gt;Eventuelle &amp;ldquo;Kompilate&amp;rdquo;, die auf unserem PC bereits da sind, da wir die App ja bereits local gebaut uns ausgeführt haben&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ursachen-beseitigen"&gt;Ursachen beseitigen&lt;/h2&gt;
&lt;p&gt;Beide Probleme können wir mit sogenannten &amp;ldquo;multi stage builds&amp;rdquo; lösen. Dabei werden unterschiedliche Images für das Erstellen der App (Kompilieren) und für finale Image genutzt. Dabei bekommt das finale Image nur die fertig kompilierte App.&lt;/p&gt;
&lt;p&gt;Dafür müssen wir nur wenige Änderungen an unserem Bauplan durchführen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Image für Build
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;- FROM mcr.microsoft.com/dotnet/sdk:10.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Verzeichnis für das Build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit &lt;code&gt;AS &amp;lt;name&amp;gt;&lt;/code&gt; vergeben wir diesen ersten Schritt (Stage) einen Namen, so dass wir später uns auf diesen beziehen können.&lt;/p&gt;
&lt;p&gt;Für den zweiten Schritt benötigen wir ein schlankeres Basis-Image. Da wir am Ende die Applikation nur ausführen möchten, ist SDK überdimensioniert. Uns reicht für unsere Zwecke die runtime (Ausführung) Version. Das Image dazu bei Microsoft heißt &lt;code&gt;mcr.microsoft.com/dotnet/aspnet:9.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Alle Schritte in der Bauanleitung (Dockerfile), die mit dem finalen Image zu tun haben, werden auf dem &amp;ldquo;runtime&amp;rdquo; Basis-Image ausgeführt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;RUN dotnet publish BlazorWebAppMovies.csproj -c Release -o /app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ # Image für Runtime
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ FROM mcr.microsoft.com/dotnet/aspnet:10.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;# Verzeichnis für die App
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;WORKDIR /app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ # Kopieren des aus dem Build zu Runtime Image
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ COPY --from=build /app .
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;# Datenbank Connection string
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;ENV CONNECTIONSTRINGS__BLAZORWEBAPPMOVIESCONTEXT=&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;In der Zeile &lt;mark&gt;4&lt;/mark&gt; definieren wir das Image, das als Basis für unser eigenes Image dienen soll (hier &lt;code&gt;aspnet&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In der Zeile &lt;mark&gt;8&lt;/mark&gt; kopieren wir die fertig kompilierte Applikation aus dem SDK-Schritt (´from=build´) und Ordner &lt;code&gt;/app&lt;/code&gt; in den aktuellen Arbeitsordner. Damit enthält das fertige Image weder den Quellcode, noch die &amp;ldquo;Zwischen-Dateien&amp;rdquo;, die beim Kompilieren entstehen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bauen wir nun unser Image mit der aktuellen Version von Dockerfile und vergeben die Version &lt;code&gt;from-aspnet&lt;/code&gt; an das Image.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Image für Build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verzeichnis für das Build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Kopiere das Projekt in das Arbeitsverzeichnis&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Wiederherstellen der Abhängigkeiten&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet restore&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Veröffentlichen der App in das Verzeichnis /app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet publish BlazorWebAppMovies.csproj -c Release -o /app&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Image für Runtime&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/aspnet:10.0&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verzeichnis für die App&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Kopieren des aus dem Build zu Runtime Image&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;build /app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Datenbank Connection string&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; &lt;span class="nv"&gt;CONNECTIONSTRINGS__BLAZORWEBAPPMOVIESCONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Port für Webserver&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# App in Container starten&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;BlazorWebAppMovies.dll&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker build -t blazor-movies:from-runtime .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unser Image ist nun deutlich kleiner geworden. Auf meinem MacBook Air ist das Image nun 462 MB, also 2.0 GB kleiner als unser erster Versuch.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE ID DISK USAGE CONTENT SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blazor-movies:from-runtime 42c8d3bed245 462MB 116MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blazor-movies:from-sdk e561bfaae17f 2.55GB 758MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcr.microsoft.com/dotnet/aspnet:10.0 eaa79205c3ad 369MB 92.4MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcr.microsoft.com/dotnet/sdk:10.0 d1823fecac36 1.29GB 318MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ein großer Teil kommt vom kleineren Basis-Image. Diese Änderung bringt bereits über 920 MB Ersparnis (von 1.3 GB runter auf 369 MB). Der Rest kommt durch das Weglassen des Quellcodes und der temporären Dateien, die beim Kompilieren entstehen.&lt;/p&gt;
&lt;h2 id="weitere-optimierungen"&gt;Weitere Optimierungen&lt;/h2&gt;
&lt;p&gt;Wir können unser Image noch weiter Optimieren. Die Standard-Images von Microsoft basieren normalerweise auf Debian, zwar einer sehr schlanken Version davon, aber immer noch mit einen vollwertigen Linux als Basis. Wir kennen bereits ein minimalistisches Linux, das selbst nur 20MG groß ist, &lt;code&gt;alpine&lt;/code&gt; Linux.&lt;/p&gt;
&lt;p&gt;Microsoft liefert alle eigene Basis-Images auch in der Alpine-Version.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Image für Build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verzeichnis für das Build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Kopiere das Projekt in das Arbeitsverzeichnis&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; . ./&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Wiederherstellen der Abhängigkeiten&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet restore&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Veröffentlichen der App in das Verzeichnis /app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; dotnet publish BlazorWebAppMovies.csproj -c Release -o /app&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Image für Runtime&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/aspnet:10.0-alpine&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verzeichnis für die App&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/app&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Kopieren des aus dem Build zu Runtime Image&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;build /app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Datenbank Connection string&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENV&lt;/span&gt; &lt;span class="nv"&gt;CONNECTIONSTRINGS__BLAZORWEBAPPMOVIESCONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Port für Webserver&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;8080&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# App in Container starten&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;BlazorWebAppMovies.dll&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; docker build -t blazor-moviews:from-alpine .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun sieht unser Image noch kleiner aus. Das Basis-Image ist von 369 MB runter auf 183 MB. Und unser eigener Image ist nun von 462 MB runter auf 276 MB. Das ist 11% von unseren Ausgangspunkt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker image ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IMAGE ID DISK USAGE CONTENT SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blazor-movies:from-alpine bb332d7cf91c 276MB 76MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blazor-movies:from-runtime 42c8d3bed245 462MB 116MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blazor-movies:from-sdk e561bfaae17f 2.55GB 758MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcr.microsoft.com/dotnet/aspnet:10.0 eaa79205c3ad 369MB 92.4MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcr.microsoft.com/dotnet/aspnet:10.0-alpine 1be14b20e4ec 183MB 51.9MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcr.microsoft.com/dotnet/sdk:10.0 d1823fecac36 1.29GB 318MB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Abhängig von der Programmiersprache und deren Fähigkeiten, lässt sich die finale Applikation noch weiter verkleinern (und somit auch das Image). Das erfordert aber sehr oft deutlich mehr aufwand. Mit Asp.Net wäre es möglich bei einigen Applikationen AOT (Ahead of Time) Kompilierung durchzuführen, so dass gar keine Runtime mehr benötigt wird. Mit Trimming (Abschneiden der nicht genutzten Fähigkeiten) kann die kompilierte Applikation noch weiter verkleinert werden.&lt;/p&gt;
&lt;p&gt;Mit den einfachen Mitteln haben wir aber bereits ein sehr kleines Image erstellt, das für die meisten Anforderungen gut genug ist.&lt;/p&gt;
&lt;h2 id="vorteil-von-alpine-linux"&gt;Vorteil von Alpine Linux&lt;/h2&gt;
&lt;p&gt;Der größte Vorteil von Alpine Linux ist nicht die Größe, sondern die Sicherheit. Da dieses Linux fast nichts hat, kann es weniger kompromittiert werden. Das ist direkt sichtbar in Docker Desktop. Für SDK Image liegen aktuell &lt;strong&gt;14&lt;/strong&gt; bekannte Schwachstellen (7 in Debian und 7 in SDK selbst), Runtime hat immer noch &lt;strong&gt;8&lt;/strong&gt;, Alpine hat nur &lt;strong&gt;2&lt;/strong&gt; (mit niedriger Wertung).&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Das Bild der Schwachstellen ist eine Momentaufnahme und wird bei Ihnen anders aussehen. Allgemeines Bild, dass Alpine-Images deutlich weniger Schwachstellen aufweisen, wird aber bleiben.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/multi_stage/sdk_vulnerabilities.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;14 Schwachstellen in SDK Image&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/multi_stage/alpine_vulnerabilities.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;2 Schwachstellen in SDK Image&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Änderungen zwischen Version anzeigen</title><link>https://kurse.richter.consulting/courses/git/diff/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/diff/</guid><description>&lt;p&gt;Wenn man mit der Zeit eine Versionshistorie aufgebaut hat, kommt der Zeitpunkt, wenn man zwei Versionen einer Datei miteinander vergleichen möchte. Dazu bietet git den Befehl &lt;code&gt;diff&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; an, der mit einigen Parametern gesteuert werden kann.&lt;/p&gt;
&lt;p&gt;Legen wir zuerst ein paar Commits mit Änderungen an, damit etwas zum Anschauen haben. Aktuell ist unsere Datei &lt;code&gt;kapitel_1.txt&lt;/code&gt; leer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Commit 1
&lt;ul&gt;
&lt;li&gt;Inhalt
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Es war ein Mal...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Message: &lt;code&gt;Kapitel 1 der Geschichte starten&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Commit 2
&lt;ul&gt;
&lt;li&gt;Inhalt
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Viele Jahre später ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Message: &lt;code&gt;Fortsetzung in vielen Jahren&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Commit 3
&lt;ul&gt;
&lt;li&gt;Inhalt
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Das Kaffee, dass damals an diesem Platz stand, existiert nicht mehr.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Message: &lt;code&gt;Treffen nach 20 Jahren&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Am Ende sollte der Inhalt der Datei wie folgt aussehen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Es war ein Mal...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Viele Jahre später ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Das Kaffee, dass damals an diesem Platz stand, existiert nicht mehr.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Und die Historie mit unserem Alias &lt;code&gt;pl&lt;/code&gt; sollte in etwa wie folgt aussehen (die Hashwerte sind bei Ihnen natürlich ganz anders).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="aktuelle-änderungen-zeigen"&gt;Aktuelle Änderungen zeigen&lt;/h2&gt;
&lt;p&gt;Ruft man den Befehl &lt;code&gt;git diff &amp;lt;Dateiname&amp;gt;&lt;/code&gt; ohne weitere Parameter auf, zeigt dieses die aktuellen Änderungen an, also was sich seit dem letzTen Commit in der Datei geändert hat. Rufen Sie es mit einer Datei, die keine Änderungen hat, gibt der Befehl nichts aus.&lt;/p&gt;
&lt;p&gt;Ohne einen Dateinamen werden die Änderungen vom kompletten Repository angezeigt. Die Anzeige erfolgt dabei im &lt;strong&gt;DIFF&lt;/strong&gt; Format. Die neuen Zeilen werden über ein &lt;code&gt;+&lt;/code&gt; vor der Zeile angezeigt, entferne mit einem &lt;code&gt;-&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ändern Sie nun unsere Datei &lt;code&gt;kapitel_1.txt&lt;/code&gt; wie folgt, ohne die Änderungen in die Versionsverwaltung festzuschreiben:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Entfernen Sie die Zeile 3 (&lt;code&gt;Viele Jahre später ...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Fügen Sie nach der Zeile 3 folgendes ein
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sie verabredeten sich in ihrem alten Kaffee zu treffen,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dass sie immer nach der Schule besucht haben.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Der text sollte nun wie folgt aussehen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Es war ein Mal...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sie verabredeten sich in ihrem alten Kaffee zu treffen,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dass sie immer nach der Schule besucht haben.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Das Kaffee, dass damals an diesem Platz stand, existiert nicht mehr.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rufen Sie nun den Befehl &lt;code&gt;git diff&lt;/code&gt; auf (mit oder ohne den Dateinamen).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git diff kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;diff --git a/kapitel_1.txt b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;index 20f47a6..8cc2eca 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;--- a/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+++ b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;@@ -1,5 +1,6 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; # Kapitel 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Es war ein Mal...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;-Viele Jahre später ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Nach 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+Sie verabredeten sich in ihrem alten Kaffee zu treffen,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+dass sie immer nach der Schule besucht haben.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Das Kaffee, dass damals an diesem Platz stand, existiert nicht mehr.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;\ No newline at end of file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wir sehen hier in DIFF Format, dass eine Zeile (nach &amp;ldquo;Es war ein Mal&amp;hellip;&amp;rdquo;) entfernt wurde, und zwei Zeilen (zwischen &amp;ldquo;Nach 20 Jahren treffen sich die Freunde wieder.&amp;rdquo; und &amp;ldquo;Das Kaffee, dass damals an diesem Platz stand, existiert nicht mehr.&amp;rdquo;) dazu gekommen sind.&lt;/p&gt;
&lt;p&gt;Diese Anzeige zeigt den Unterschied zwischen dem letzten Commit und der aktuellen Arbeitsversion.&lt;/p&gt;
&lt;h2 id="unterschiede-zwischen-zwei-commits"&gt;Unterschiede zwischen zwei Commits&lt;/h2&gt;
&lt;p&gt;Wollen wir die Datei zwischen zwei bestimmten Versionen (Commits) vergleichen, müssen wird das &lt;code&gt;diff&lt;/code&gt; Commando mit wenigen Parametern erweitern. Die sehr umfangreiche Liste der möglichen Parameter kann mit &lt;code&gt;git diff --help&lt;/code&gt; aufgerufen werden. Uns interessieren aktuell nur die zwei gängigsten, bei denen die zwei &lt;strong&gt;Anker&lt;/strong&gt; mit angegeben werden. Ein Anker kann dabei ein Commit, ein Branch oder ein Tag sein.&lt;/p&gt;
&lt;p&gt;Als Erstes können wir explizit zwei Commit angeben, die wir miteinander vergleichen wollen. Die Commit-Hashes können wir sehr einfach mit unserem &lt;code&gt;git pl&lt;/code&gt; Alias anzeigen lassen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 (HEAD -&amp;gt; main) Treffen nach 20 Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel 1 der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file for temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git diff c3b4e8b bd4b2df
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;diff --git a/kapitel_1.txt b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;index e69de29..61a6fe5 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;--- a/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+++ b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;@@ -0,0 +1,3 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+# Kapitel 1^M
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+Es war ein Mal...^M
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+Viele Jahre später ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;\ No newline at end of file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="head-anker-für-diff-nutzen"&gt;&lt;code&gt;HEAD&lt;/code&gt; Anker für &lt;code&gt;diff&lt;/code&gt; nutzen&lt;/h2&gt;
&lt;p&gt;Wenn Sie in der Historie nur wenige Commits zurückgehen wollen, lässt sich das auch mit dem &lt;code&gt;HEAD&lt;/code&gt; Zeiger erledigen. &lt;code&gt;HEAD&lt;/code&gt; steht immer auf dem letzten Commit. Mit der &lt;code&gt;^&lt;/code&gt; und &lt;code&gt;~x&lt;/code&gt; Syntax kann man vom &lt;code&gt;HEAD&lt;/code&gt; aus 1 oder &lt;code&gt;x&lt;/code&gt; Commits zurückgehen. Das obere Ergebnis erreichen wir also auch mit dem folgenden Befehl (ohne die Commit-Hashes zu kennen).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git diff HEAD~3 HEAD^ kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;diff --git a/kapitel_1.txt b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;index e69de29..61a6fe5 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;--- a/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+++ b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;@@ -0,0 +1,3 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+# Kapitel 1^M
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+Es war ein Mal...^M
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+Viele Jahre später ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;\ No newline at end of file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="reihenfolge-ist-wichtig"&gt;Reihenfolge ist wichtig&lt;/h2&gt;
&lt;p&gt;Passen Sie auf die Reihenfolge auf. Im Normalfall interessiert Sie, was seit einem bestimmten Commit passiert ist, die Reihenfolge der Parameter ist also älterer Commit und dann neuerer. Wenn Sie die Parameter vertauschen, erhalten Sie die Ansicht, was müsste gemacht werden, um den &lt;em&gt;ursprünglichen&lt;/em&gt; Zustand wieder zu erhalten.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git diff HEAD^ HEAD~3 kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;diff --git a/kapitel_1.txt b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;index 61a6fe5..e69de29 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;--- a/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+++ b/kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;@@ -1,3 +0,0 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;-# Kapitel 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;-Es war ein Mal...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;-Viele Jahre später ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;\ No newline at end of file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Schreiben Sie nun die letzte, noch nicht festgeschriebene Änderung an unserer Datei fest.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Damit wir nicht jedes Mal zwei Befehle ausführen müssen (&lt;code&gt;add&lt;/code&gt; + &lt;code&gt;commit&lt;/code&gt;), können wir beides kombinieren. Dabei werden alle geänderten / gelöschten Dateien in das Stating-Bereich übernommen und in den Commit aufgenommen. Neue Dateien (die noch nicht unter Versionsverwaltung stehen) werden dabei nicht berücksichtigt. Diese müssen zuerst mit &lt;code&gt;git add&lt;/code&gt; hinzugefügt werden.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/repo_1$ git commit -a -m &lt;span class="s2"&gt;&amp;#34;Korrekturen am Kapitel 1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;main 027c2f3&lt;span class="o"&gt;]&lt;/span&gt; Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;2&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="m"&gt;1&lt;/span&gt; deletion&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Der Parameter &lt;code&gt;-a&lt;/code&gt; (oder auch in der Langschreibweise &lt;code&gt;--all&lt;/code&gt;) führt zu der gewollten Aktion.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Eigenes Image veröffentlichen</title><link>https://kurse.richter.consulting/courses/container/publishing/</link><pubDate>Sun, 08 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/publishing/</guid><description>&lt;p&gt;Nun haben wir das Image erstellt. Aktuell befindet sich dieses aber nur auf unserem eigenen Rechner. D.h. keiner, außer uns, kann dieses Image nutzen. Damit auch andere unser Image nutzen können, müssen wir dieses veröffentlichen. Dazu benötigen wir als erstes eine Container-Registry.&lt;/p&gt;
&lt;h2 id="container-registry"&gt;Container Registry&lt;/h2&gt;
&lt;p&gt;Container Registry ist ein zentraler Speicherort für die fertig gebauten Images.
Es gibt einige Anbieter dafür, sowohl öffentlich zugängliche als auch solche, die private Images verwalten.&lt;/p&gt;
&lt;p&gt;Die bekannteste Registry ist von der Firma Docker selbst und heißt
.
Diese erlaubt ein kostenloses privates Repository und unbegrenzt für Open Source Projekte.&lt;/p&gt;
&lt;p&gt;Daneben bietet fast jeder größerer Cloud-Anbieter eine Container-Registry in deren Cloud-Umgebung:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;und viele weitere.&lt;/p&gt;
&lt;h2 id="docker-hub"&gt;Docker Hub&lt;/h2&gt;
&lt;p&gt;Hier werden wir Docker Hub als Beispiel nutzen. Das Vorgehen mit anderen Anbietern ist oft ähnlich.
Für alle können dieselben Docker-Befehle genutzt werden.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Legen Sie als erstes ein Konto bei
an, falls Sie noch keinen haben.&lt;/li&gt;
&lt;li&gt;Erstellen Sie ein neues Repository (Speicherort für Images einer Anwendung) an, z.B. &lt;code&gt;blazor-movies&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Erstellen Sie ein &amp;ldquo;Personal Access Token&amp;rdquo;, um auf den Docker Hub einfacher zugreifen zu können (und sicherer - insbesondere in CI/CD Umgebungen).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="personal-access-token-erstellen"&gt;Personal Access Token Erstellen&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Klicken Sie auf Ihren Avatar oben rechts, um zu den &amp;ldquo;Account Settings&amp;rdquo; zu gelangen.
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/publishing/hub_account_settings.png"
alt="Flyout menu on avatar"&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Öffnen Sie nun im Bereich &amp;ldquo;Settings&amp;rdquo; die Einstellungen für &amp;ldquo;Personal access tokens&amp;rdquo;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/publishing/hub_pats.png"
alt="Personal access tokens menu under security settings"&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Klicken Sie auf &amp;ldquo;Generate new token&amp;rdquo;, um einen neuen Token zu erstellen. Wählen Sie hier einen sprechenden Namen, die max. Gültigkeit des Tokens und dessen Berechtigung. Zum Veröffentlichen benötigen Sie min. Schreibrechte. Bei anderen Anbietern kann die Granularität der Berechtigungen deutlich granulärer sein.
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/publishing/hub_new_pat.png"
alt="Neues Personal Access Token erstellen"&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="vorbereiten-des-images"&gt;Vorbereiten des Images&lt;/h3&gt;
&lt;p&gt;Bevor das Image hochgeladen werden kann, muss dieser zuerst angepasst werden. Der Name kann nicht mehr so einfach sein, wie in unserem Fall vorher (&lt;code&gt;balazor-moview&lt;/code&gt;). Wie wir bereits gelernt haben, sind die &amp;ldquo;einfachen&amp;rdquo; Image-Namen für offizielle Images reserviert.&lt;/p&gt;
&lt;p&gt;Unsere Images müssen im Namen folgende Bestandteile enthalten &lt;code&gt;&amp;lt;registry&amp;gt;/&amp;lt;vendor&amp;gt;/&amp;lt;repository&amp;gt;:&amp;lt;tag&amp;gt;&lt;/code&gt;. Hier am Beispiel unseres Basis-Images &lt;code&gt;mcr.microsoft.com/dotnet/aspnet:10.0-alpine&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Registry: Bei Docker-Hub fällt dieser Teil weg. Bei anderen Registrys muss der Name der Registry angegeben werden (z.B. bei unserem Basis-Image ist es &lt;code&gt;mcr.microsoft.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Vendor: Normalerweise Hersteller der Software oder Benutzer, der die Repositories pflegt (z.B. bei unserem Basis-Image ist es &lt;code&gt;dotnet&lt;/code&gt;). Bei offiziellen Images auf Docker Hub entfällt auch dieser Teil.&lt;/li&gt;
&lt;li&gt;Repository: Speichername für die Images einer Anwendung (z.B. bei unserem Basis-Image ist es &lt;code&gt;aspnet&lt;/code&gt;). Dieser Teil ist immer notwendig&lt;/li&gt;
&lt;li&gt;Tag: Version der Anwendung (z.B. bei unserem Basis-Image ist es &lt;code&gt;10.0-alpine&lt;/code&gt;). Dieser Teil ist wieder optional. Wird Tag nicht angegeben, vergibt Docker automatisch den Tag &lt;code&gt;latest&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wir müssen unser Image, das wir veröffentlichen wollen, zuerst nach der obigen Konvention umbenennen. Aus dem aktuellen Namen &lt;code&gt;blazor-movies:from-alpine&lt;/code&gt; muss &lt;code&gt;webducer/blazor-moviews:alpine&lt;/code&gt; werden (ersetzen Sie Benutzer- und Repository-Namen mit Ihren Werten).&lt;/p&gt;
&lt;p&gt;Auf Docker Hub erhalten Sie einen Hinweis, wie das Image heißen soll in Form des &amp;ldquo;push&amp;rdquo; Befehls auf der Repository Startseite.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/publishing/hub_push_command.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Push command Hilfestellung auf der Repository Seite&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Die Umbenennung des Images erfolgt durch das erneute Taggen des vorhandenen Images mit dem
Befehl.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker image tag blazor-movies:from-alpine webducer/blazor-movies:alpine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="veröffentlichen"&gt;Veröffentlichen&lt;/h3&gt;
&lt;p&gt;Vor der Veröffentlichung müssen wir uns zuerst bei der Registry einloggen. Bei Docker Hub entfällt die Angabe der Registry. Bei allen anderen muss diese immer explizit mit angegeben werden. Das Anmelden erfolgt über den
Befehl (&lt;code&gt;docker login &amp;lt;server-name&amp;gt;&lt;/code&gt; bei nicht Docker Hub Registrys). Folgen Sie dabei den Anweisungen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun können wie unser Image veröffentlichen. Das erfolgt durch den
Befehl und der Eingabe des Image-Namens.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker push webducer/blazor-movies:alpine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das Veröffentlichen kann einige Zeit dauern, abhängig von der Größe des Images und Ihrer Internetverbindung. Beim &lt;code&gt;push&lt;/code&gt; wird normalerweise nicht das ganze Image übertragen, sondern nur die &amp;ldquo;unbekannten&amp;rdquo; Schichten. Da meistens das Basis-Image bereits in Registry bekannt ist, müssen nur die Schichten oberhalb von diesen Basis-Image übertragen werden.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/publishing/hub_image.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Repository nach Veröffentlichung&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;&lt;img src="https://kurse.richter.consulting/courses/container/publishing/hub_image_detail.png"&gt;&lt;figcaption&gt;
&lt;h4&gt;Details des Images&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;</description></item><item><title>Verzweigungen (Branches) anlegen</title><link>https://kurse.richter.consulting/courses/git/branches/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/branches/</guid><description>&lt;p&gt;Früher oder später braucht man mehr als nur eine lineare Entwicklung auf einen einzigen Zweig. Der einfachste Ansatz dazu, ist mit &lt;code&gt;main&lt;/code&gt; und &lt;code&gt;develop&lt;/code&gt; Zweigen zu arbeiten. Dabei erfolgt auf dem &lt;code&gt;develop&lt;/code&gt; Zweig die eigentliche Entwicklung. Auf dem &lt;code&gt;main&lt;/code&gt; Zweig landen dann die &lt;strong&gt;auslieferungsfähige&lt;/strong&gt; Versionen, die oft auch benannt werden (Tags - siehe übernächstes Kapitel).&lt;/p&gt;
&lt;h2 id="branches-anzeigen"&gt;Branches anzeigen&lt;/h2&gt;
&lt;p&gt;Verschafen wir uns zuerst die Übersicht über die aktuell im Repository vorhandenen Zweige (Branches).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git branch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wir haben aktuell also nur den Branch &lt;code&gt;main&lt;/code&gt;. Mit dem &lt;code&gt;*&lt;/code&gt; wird bei mehreren Branches immer das aktuell aktive markiert.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Eventuell sehen Sie statt &lt;code&gt;main&lt;/code&gt; einen &lt;code&gt;master&lt;/code&gt; als Brnachnamen. Das hängt davon ab, wann Sie git auf Ihrem System installiert haben. Falls Sie eine ältere Installation haben, können Sie die globale Konfiguration mit folgender Zeile umstellen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config --global init.defaultBranch main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Den vorhandenen &lt;code&gt;master&lt;/code&gt; Branch können Sie auch jederzeit auf neue Konvention umstellen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git branch -m master main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="branches-anlegen"&gt;Branches anlegen&lt;/h2&gt;
&lt;p&gt;Nun legen wir einen neuen Brnach an, den wir &lt;code&gt;develop&lt;/code&gt; nennen. Dazu wird der Befehl &lt;code&gt;branch &amp;lt;neuer_name&amp;gt;&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; genutzt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git branch develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git branch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="zum-branch-wechseln"&gt;Zum Branch wechseln&lt;/h2&gt;
&lt;p&gt;Um nun auf den neuen Branch arbeiten zu können, wecheln wir zu diesem mit dem &lt;code&gt;checkout&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; Befehl.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git branch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun können wir auf diesem Zweig unsere Änderungen durchführen und festschreiben. Führen Sie für den nächsten Schritt nun folgende Schritte durch:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Legen Sie eine neue die Datei &lt;code&gt;kapitel_2.txt&lt;/code&gt; an&lt;/li&gt;
&lt;li&gt;Versionieren Sie diese&lt;/li&gt;
&lt;li&gt;Fügen Sie folgenden Text zu der Datei:
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach einer durchzechten Nacht ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Schreiben Sie die Änderung in der Historie fest&lt;/li&gt;
&lt;li&gt;Legen Sie eine neue Datei &lt;code&gt;kapitel_3.txt&lt;/code&gt; an, ohne diese unter Versionsverwaltung zu stellen.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Am Ende sollte die Historie (und Status) in etwa wie folgt aussehen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Untracked files:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to include in what will be committed&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_3.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing added to commit but untracked files present &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="branch-verhalten"&gt;Branch Verhalten&lt;/h2&gt;
&lt;p&gt;Jetzt haben wir zwei neue Dateien im Branch &lt;code&gt;develop&lt;/code&gt; erstellt. Dabei haben wir eine davon unter die Versionsverwaltung (&lt;code&gt;kapitel_2.txt&lt;/code&gt;). In dem Ordner liegen aktuell drei Dateien (+2 aus der Ausnahmeliste).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kapitel_1.bak kapitel_1.txt kapitel_1.~ kapitel_2.txt kapitel_3.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Was passiert nun, wenn wir zurück zu &lt;code&gt;main&lt;/code&gt; wechseln? Wie wird der Ordner danach aussehen? Versuchen Sie es aus.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kapitel_1.bak kapitel_1.txt kapitel_1.~ kapitel_3.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sie haben wahrscheinlich erwartet, dass sowohl &lt;code&gt;kapitel_2.txt&lt;/code&gt; als auch &lt;code&gt;kapitel_3.txt&lt;/code&gt; nicht mehr da sind, da diese ja nicht in &lt;code&gt;main&lt;/code&gt; erstellt wurden. Tatsächlich ist nur die Datei &lt;code&gt;kapitel_2.txt&lt;/code&gt; nicht mehr da.&lt;/p&gt;
&lt;p&gt;Das ist sehr einfach zu erklären. Git kümmert sich nur um Dateien, die unter seiner Kontrolle stehen (versioniert sind). Alle anderen Dateien werden einfach ignoriert. Genau das passiert mit &lt;code&gt;kapitel_3.txt&lt;/code&gt;. Diese Datei steht noch nicht unter Versionskontrolle, weshalb diese von git unangetastet bleibt. Bei &lt;code&gt;kapitel_2.txt&lt;/code&gt; ist der Fall anders. Diese steht unter Versionskontrolle. Damit weiß git, dass diese zwar im Zweig &lt;code&gt;develop&lt;/code&gt; vorhanden ist, aber nicht in &lt;code&gt;main&lt;/code&gt;. Aus diesem grund wird diese beim Wechsel gelöscht (oder angelegt beim Wechsel zurück).&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Nicht versionierte Dateien sind für git unsichtbar und werden von diesem nicht angefasst.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="paralleles-arbeiten"&gt;Paralleles Arbeiten&lt;/h2&gt;
&lt;p&gt;Nun simulieren wir, dass auf beiden Branches nun gearbeitet wurde. Dazu versionieren wir die Datei &lt;code&gt;kapitel_3.txt&lt;/code&gt; und fügen ein wenig Text hinzu.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach zwei Monaten in der Versenkung ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das wird unsere Basis für den nächsten Kapitel, in dem wir versuchen die Branches zusammenzuführen. Am Ende sollte die Versionshistorie in etwa wie folgt aussehen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 663ea5a &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; Plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Änderungen eines Zweiges in ein Anderes übernehmen</title><link>https://kurse.richter.consulting/courses/git/merges/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/merges/</guid><description>&lt;p&gt;Nach getaner Arbeit sollen die unterschiedlichen Stände der Arbeit wieder zusammengeführt werden. Dabei kann es zu 3 Konstellationen kommen:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fast-Merge: Es wurden nur Änderungen auf neuen Branch gemacht, aber nicht auf &lt;code&gt;main&lt;/code&gt;. Damit kann git einfach den &lt;strong&gt;Zeiger&lt;/strong&gt; für &lt;code&gt;main&lt;/code&gt; Branch auf den neuen Stand setzen. In diesem Fall spricht man von &amp;ldquo;Fast Merge&amp;rdquo;. Es wird dabei kein extra Commit erzeugt.&lt;/li&gt;
&lt;li&gt;Merge: Beim Zusammenführen sind keine Probleme augetreten. In diesem Fall wir ein sogenannter &amp;ldquo;Merge&amp;rdquo;-Commit erstellt. Im Gegensatz zu einem normalen Commit, hat dieser Informationen zu den beiden Branches, statt nur einen.&lt;/li&gt;
&lt;li&gt;Conflict: Beim Zusammenführen kommt es zu einem Konflikt, den git nicht selbst lösen kann. Wir müssen alle Konflikte beseitigen und das Zusammenführen abzuschließen.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Wir werden hier alle 3 Möglichkeiten durchspielen.&lt;/p&gt;
&lt;h2 id="fast-merge"&gt;Fast Merge&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h2&gt;
&lt;p&gt;Wechseln Sie zuerst auf den &lt;code&gt;main&lt;/code&gt;-Branch, wenn noch nicht geschehen. Erstellen Sie einen neuen Branch &lt;code&gt;feat_kap_4&lt;/code&gt; und wechseln Sie zu diesem.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Da man meistens beim Erzeugen eines neuen Branches auch gleich zu diesem wechseln möchte, gibt es eine Abkürzung. Statt &lt;code&gt;git branch &amp;lt;neuer_branch_name&amp;gt;&lt;/code&gt; und &lt;code&gt;git checkout &amp;lt;neuer_branch_name&amp;gt;&lt;/code&gt; eingeben zu müssen, kann man auch kürzer den &lt;code&gt;-b&lt;/code&gt; Flag nutzen: &lt;code&gt;git checkout -b &amp;lt;neuer_branch_name&amp;gt;&lt;/code&gt; eingeben.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Already on &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout -b feat_kap_4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to a new branch &lt;span class="s1"&gt;&amp;#39;feat_kap_4&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun legen wir eine neue Datei an, mit Inhalt, den wir auch mehrere Commits verteilen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Im vierten Jahr stand der Weizen ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Darauf folgte eine dreijährige Düre...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Am Ende sollte die Historie wie folgt aussehen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 10eabc1 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; feat_kap_4&lt;span class="o"&gt;)&lt;/span&gt; Die Düre-Jahre
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 054db53 Vierter Kapitel über...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 663ea5a &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wenn man den Pfad folgt, sieht man hier sehr gut, dass &lt;code&gt;main&lt;/code&gt; eigentlich auf demselben Pfad liegt, wie unser neuer Branch &lt;code&gt;feat_kap_4&lt;/code&gt;. Das ist die Voraussetzung für einen &amp;ldquo;Fast-Merge&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Wechseln wir nun zurück zu &lt;code&gt;main&lt;/code&gt;. Anschließen führen wir die Beiden Zweige zusammen. Dazu muss man immer auf dem Branch drauf sein, in dem man den anderen Zweig integrieren will. Die Integration wird mit &lt;code&gt;git merge &amp;lt;branch_name&amp;gt;&lt;/code&gt; durchgeführt. In der Ausgabe sollte nun sichtbar sein, dass ein &amp;ldquo;Fast-Merge&amp;rdquo; durchgeführt wurde.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git merge feat_kap_4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updating 663ea5a..10eabc1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Fast-forward
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_4.txt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; ++++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;4&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Auch an dem Log ist es sichtbar, dass ein &amp;ldquo;Fast-Merge&amp;rdquo; erstellt wurde:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Es sind genauso viele Commits da, wie vorher.&lt;/li&gt;
&lt;li&gt;Letzter Commit hat denselben Hash. D.h. dieser wurde nicht geändert.&lt;/li&gt;
&lt;li&gt;Beide Branches, &lt;code&gt;main&lt;/code&gt; und &lt;code&gt;feat_kap_4&lt;/code&gt; zeigen auf denselben Commit.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 10eabc1 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main, feat_kap_4&lt;span class="o"&gt;)&lt;/span&gt; Die Düre-Jahre
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 054db53 Vierter Kapitel über...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 663ea5a Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Da die Zusammenführung erfolgreich war, können wir den nicht mehr benötigten Branch &lt;code&gt;feat_kap_4&lt;/code&gt; mit &lt;code&gt;git branch -d &amp;lt;branch_name&amp;gt;&lt;/code&gt; löschen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git branch -d feat_kap_4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Deleted branch feat_kap_4 &lt;span class="o"&gt;(&lt;/span&gt;was 10eabc1&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="merge"&gt;Merge&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/h2&gt;
&lt;p&gt;Für eine &amp;ldquo;normale&amp;rdquo; Zusammenführung haben wir auch bereits alles vorbereitet. Wir haben zwei Branches, auf denen parallel gearbeitet wurde, &lt;code&gt;main&lt;/code&gt; und &lt;code&gt;develop&lt;/code&gt;. Nun können wir wieder auf &lt;code&gt;main&lt;/code&gt; wechsel, falls noch nicht der Fall ist, und &lt;code&gt;develop&lt;/code&gt; integrieren.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Already on &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git merge develop
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Merge made by the &lt;span class="s1"&gt;&amp;#39;ort&amp;#39;&lt;/span&gt; strategy.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_2.txt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; ++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;2&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_2.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e779542 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 10eabc1 Die Düre-Jahre
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 054db53 Vierter Kapitel über...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 663ea5a Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An dem Log können wir sehr gut sehen, dass es dieses Mal ein neuer Commit (&lt;code&gt;e779542&lt;/code&gt;) erzeugt wurde, der mit zwei anderen Commits (&lt;code&gt;aac4d8b&lt;/code&gt; und &lt;code&gt;10eabc1&lt;/code&gt;) verbunden ist.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Konflikte beim Zusammenführen lösen</title><link>https://kurse.richter.consulting/courses/git/conflicts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/conflicts/</guid><description>&lt;p&gt;Erstellen wir für einen Konflikt zuerst einen neuen Branch.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout -b feat_kap_5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to a new branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Erstellen Sie nun eine neue Datei &lt;code&gt;kapitel_5.txt&lt;/code&gt; mit dem folgenden Inhalt und fügen Sie diese Datei zur Versionsverwaltung.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 5
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach 8 stünddiger Fahrt ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_repo_1&amp;gt; git commit -m &lt;span class="s2"&gt;&amp;#34;Fahrt im Zug&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;feat_kap_5 1b28574&lt;span class="o"&gt;]&lt;/span&gt; Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;2&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_5.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Jetzt ändern wir bereits vorhandene Dateien, um einige Konflikte zu provozieren. Ändern Sie die Datei &lt;code&gt;kapitel_1.txt&lt;/code&gt; wie folgt (&lt;code&gt;+&lt;/code&gt;-neuer Inhalt, &lt;code&gt;-&lt;/code&gt;-gelöschter Inhalt).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Es war ein Mal...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;- Nach 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ Nach langen 19 Jahren trafen sich die Freunde wieder,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ um neue Pläne zu schmieden.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Sie verabredeten sich in ihrem alten Kaffee zu treffen,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ändern Sie noch die Datei &lt;code&gt;kapitel_4.txt&lt;/code&gt; wie folgt.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Im vierten Jahr stand der Weizen ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;- Darauf folgte eine dreijährige Düre...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ Nach 3 Jahren der sehr guten Ernten kam nun die Dürre,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ die die nächsten 8 Jahre andauern sollte.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das Log sollte in etwa wie unten aussehen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 408a803 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; feat_kap_5&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 47c1c6d Kapitel &lt;span class="m"&gt;1&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 1b28574 Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e779542 &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 10eabc1 Die Düre-Jahre
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 054db53 Vierter Kapitel über...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 663ea5a Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wechseln wir nun auf den &lt;code&gt;main&lt;/code&gt; Branch und machen mit den Änderungen weiter.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Auch hier ändern wird die beiden Dateien &lt;code&gt;kapitel_1.txt&lt;/code&gt; und &lt;code&gt;kapitel_4.txt&lt;/code&gt; an denselben Zeilen. Zusätzlich legen wir auch einen neuen Kapitel 6 an.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;- Nach 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ Nach nicht ganz 20 Jahren treffen sich die Freunde wieder.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;- Darauf folgte eine dreijährige Düre...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ Darauf folgte eine achtjährige Dürre...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vor dem Zusammenführena sollte das Log nun wie folgt aussehen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 618450e &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;6&lt;/span&gt; gestartet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 54a8d9a Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 0b1ad44 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; ausgearbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 408a803 &lt;span class="o"&gt;(&lt;/span&gt;feat_kap_5&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 47c1c6d Kapitel &lt;span class="m"&gt;1&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 1b28574 Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e779542 Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 10eabc1 Die Düre-Jahre
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 054db53 Vierter Kapitel über...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 663ea5a Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Versuchen Sie nun die Zusammenführung. Diese sollte nun scheitern, da git nicht in der Lage ist, die Konflikte zu lösen. Die Änderungen sind auf beiden Branches in denselben Zeilen. Wir müssen die Konflikte manuell lösen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git merge feat_kap_5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Auto-merging kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONFLICT &lt;span class="o"&gt;(&lt;/span&gt;content&lt;span class="o"&gt;)&lt;/span&gt;: Merge conflict in kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Auto-merging kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONFLICT &lt;span class="o"&gt;(&lt;/span&gt;content&lt;span class="o"&gt;)&lt;/span&gt;: Merge conflict in kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Automatic merge failed&lt;span class="p"&gt;;&lt;/span&gt; fix conflicts and &lt;span class="k"&gt;then&lt;/span&gt; commit the result.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="übernahme-einer-der-versionen"&gt;Übernahme einer der Versionen&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/h3&gt;
&lt;p&gt;Der &lt;code&gt;main&lt;/code&gt; Brnach befindet sich wegen dem Konflikt nun in einem &amp;ldquo;Merge&amp;rdquo; Status. Mit &lt;code&gt;git status&lt;/code&gt; können wir immer den aktuellen Stand bei Konfliktlösung sehen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You have unmerged paths.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;fix conflicts and run &lt;span class="s2"&gt;&amp;#34;git commit&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git merge --abort&amp;#34;&lt;/span&gt; to abort the merge&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Changes to be committed:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; new file: kapitel_5.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unmerged paths:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to mark resolution&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; both modified: kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; both modified: kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bei dem Konflikt im Kapitel 1 möchten wir einfach die Änderungen aus dem Branch &lt;code&gt;feat_kap_4&lt;/code&gt; übernehmen. Dazu nutzen wir den &lt;code&gt;checkout&lt;/code&gt; Befehl mit dem &lt;code&gt;--theirs&lt;/code&gt; oder &lt;code&gt;--ours&lt;/code&gt; Parameter und dem Dateinamen.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--theirs&lt;/code&gt;: Es wird die Version aus dem &lt;strong&gt;anderen&lt;/strong&gt; Branch genommen. Da wir auf &lt;code&gt;main&lt;/code&gt; sind, ist es die Version aus Branch &lt;code&gt;feat_kap_5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--ours&lt;/code&gt;: Es wird unsere Version genommen, also aus dem &lt;code&gt;main&lt;/code&gt; Branch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nach dem Auschecken der gewollten Version muss die Lösung des Konfliktes mit &lt;code&gt;git add&lt;/code&gt;, beendet werden.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout --theirs -- kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git add kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;You have unmerged paths.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;fix conflicts and run &lt;span class="s2"&gt;&amp;#34;git commit&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git merge --abort&amp;#34;&lt;/span&gt; to abort the merge&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Changes to be committed:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; modified: kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; new file: kapitel_5.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unmerged paths:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to mark resolution&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; both modified: kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="manuelle-korrekturen"&gt;Manuelle Korrekturen&lt;/h3&gt;
&lt;p&gt;Nun haben wir noch ein Konflikt, in der Datei &lt;code&gt;kapitel_4.txt&lt;/code&gt;. Diesen Konflikt möchten wir manuell lösen, da wir Änderungen aus beiden Branches kombinieren möchten. Aktuell sieht die Datei wie folgt aus:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Im vierten Jahr stand der Weizen ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Darauf folgte eine achtjährige Düre...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;=======
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nach 3 Jahren der sehr guten Ernten, kam nun die Dürre,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;die die nächsten 8 Jahre andauern sollte.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; feat_kap_5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;/code&gt;: Markierung für den Start des Bereiches mit den Änderungen aus dem aktuellen Branch.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;=======&lt;/code&gt;: Markierung zur Trennung zwischen den Änderungen aus den beiden Brnaches.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; feat_kap_5&lt;/code&gt;: Markierung zum Ende der Änderungen aus dem &lt;em&gt;anderen&lt;/em&gt; Branch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Die Datei können wir nun manuell bearbeiten und in den Zustand bringen, den wir haben möchten. Die &lt;em&gt;Markierungen&lt;/em&gt; sollen am Ende alle entfernt werden.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Im vierten Jahr stand der Weizen ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Darauf folgte eine achtjährige Dürre...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Die die nächsten 8 Jahre andauern sollte.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Auch die Lösung von diesem Konflikt muss mit &lt;code&gt;git add&lt;/code&gt; beendet werden. Der gesammte Merge wird dann über ein &lt;code&gt;git commit&lt;/code&gt; abgeschlossen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git add kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;All conflicts fixed but you are still merging.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git commit&amp;#34;&lt;/span&gt; to conclude merge&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Changes to be committed:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; modified: kapitel_1.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; modified: kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; new file: kapitel_5.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git commit -m &lt;span class="s2"&gt;&amp;#34;Merge branch &amp;#39;feat_kap_5&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;main 7a000b4&lt;span class="o"&gt;]&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Historie sollte nun unsere erfolgreiche Zusammenführung anzeigen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 7a000b4 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 408a803 &lt;span class="o"&gt;(&lt;/span&gt;feat_kap_5&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 47c1c6d Kapitel &lt;span class="m"&gt;1&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 1b28574 Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 618450e Kapitel &lt;span class="m"&gt;6&lt;/span&gt; gestartet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 54a8d9a Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 0b1ad44 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; ausgearbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e779542 Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * aac4d8b &lt;span class="o"&gt;(&lt;/span&gt;develop&lt;span class="o"&gt;)&lt;/span&gt; Nachtszene
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * e6b896a Ideen zum zweiten Kapitel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 10eabc1 Die Düre-Jahre
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 054db53 Vierter Kapitel über...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 663ea5a Versenkung
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 63bb3f0 Kapitel &lt;span class="m"&gt;3&lt;/span&gt; plot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 027c2f3 Korrekturen am Kapitel &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e4c2672 Treffen nach &lt;span class="m"&gt;20&lt;/span&gt; Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* bd4b2df Fortsetzung in vielen Jahren
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e47bbe0 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; der Geschichte starten
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* c3b4e8b Add repo ignore file &lt;span class="k"&gt;for&lt;/span&gt; temp files
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e12fb6d feat: Start des ersten Kapitels
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Rebase: Verzweigung auf neue Basis setzen</title><link>https://kurse.richter.consulting/courses/git/rebase/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/rebase/</guid><description>&lt;p&gt;Als Alternative für ein &lt;code&gt;merge&lt;/code&gt;, kann auch ein &lt;code&gt;rebase&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; gemacht werden. Die Unterschiede schauen wir uns jetzt an.&lt;/p&gt;
&lt;h2 id="was-ist-ein-rebase"&gt;Was ist ein &lt;code&gt;rebase&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Git Rebase ist eine Methode, um die Commit-Historie zu verändern und zu bereinigen. Im Gegensatz zu &lt;code&gt;git merge&lt;/code&gt;, der zwei Branches zusammenführt und einen neuen Merge-Commit erstellt, sortiert git &lt;code&gt;rebase&lt;/code&gt; die Commits neu und wendet sie in linearer Folge an, was eine sauberere Projekthistorie erzeugt.&lt;/p&gt;
&lt;h2 id="ablauf-bei-einem-rebase"&gt;Ablauf bei einem &lt;code&gt;rebase&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Bei einem Rebase nimmt Git alle Commits aus deinem aktuellen Branch (z.B. &lt;code&gt;feature-branch&lt;/code&gt;) und wendet sie erneut auf einen anderen Branch (z.B. &lt;code&gt;main&lt;/code&gt;) an. Dies geschieht wie folgt:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Git identifiziert den gemeinsamen Vorfahren-Commit beider Branches&lt;/li&gt;
&lt;li&gt;Git speichert temporäre Kopien der Änderungen jedes Commits im Feature-Branch&lt;/li&gt;
&lt;li&gt;Der Feature-Branch wird auf den Ziel-Branch (&lt;code&gt;main&lt;/code&gt;) zurückgesetzt&lt;/li&gt;
&lt;li&gt;Die gespeicherten Änderungen werden einzeln als neue Commits auf den Ziel-Branch angewendet (die Historie ändert sich damit)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;figure id="figure-graph-für-git-merge"&gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="Git merge graph"
srcset="https://kurse.richter.consulting/courses/git/rebase/git-merge_hu_22ee2a5e0630f102.webp 320w, https://kurse.richter.consulting/courses/git/rebase/git-merge_hu_a86054996ea523aa.webp 480w, https://kurse.richter.consulting/courses/git/rebase/git-merge_hu_4c09d2e5b3fff98.webp 760w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://kurse.richter.consulting/courses/git/rebase/git-merge_hu_22ee2a5e0630f102.webp"
width="760"
height="307"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;figcaption&gt;
Graph für git merge
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;figure id="figure-git-graph-vor-dem-rebase"&gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="Git branch graph"
srcset="https://kurse.richter.consulting/courses/git/rebase/git-before-rebase_hu_363b3a62ab9af044.webp 320w, https://kurse.richter.consulting/courses/git/rebase/git-before-rebase_hu_42f0f1404c66316e.webp 480w, https://kurse.richter.consulting/courses/git/rebase/git-before-rebase_hu_b072b6264cb4fd46.webp 760w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://kurse.richter.consulting/courses/git/rebase/git-before-rebase_hu_363b3a62ab9af044.webp"
width="760"
height="407"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;figcaption&gt;
Git Graph vor dem Rebase
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;figure id="figure-git-graph-nach-dem-rebase"&gt;
&lt;div class="flex justify-center "&gt;
&lt;div class="w-full" &gt;
&lt;img alt="Git branch graph after rebase"
srcset="https://kurse.richter.consulting/courses/git/rebase/git-after-rebase_hu_de6c85b0b22c19e7.webp 320w, https://kurse.richter.consulting/courses/git/rebase/git-after-rebase_hu_3a60047272e07cc6.webp 480w, https://kurse.richter.consulting/courses/git/rebase/git-after-rebase_hu_444a064a15c6249e.webp 760w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 90vw, (max-width: 1024px) 80vw, 760px"
src="https://kurse.richter.consulting/courses/git/rebase/git-after-rebase_hu_de6c85b0b22c19e7.webp"
width="760"
height="314"
loading="lazy" data-zoomable /&gt;&lt;/div&gt;
&lt;/div&gt;&lt;figcaption&gt;
Git Graph nach dem Rebase
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="einen-rebase-durchführen"&gt;Einen &lt;code&gt;rebase&lt;/code&gt; durchführen&lt;/h2&gt;
&lt;p&gt;Um en &lt;code&gt;rebase&lt;/code&gt; zu erstellen, sollten wir vorher Änderungen auf zwei Verzweigungen erstellen, so dass ein &lt;code&gt;merge&lt;/code&gt; nicht mehr durch ein &amp;ldquo;fast forward&amp;rdquo; durchgeführt werden kann.&lt;/p&gt;
&lt;p&gt;Erstellen wir für Rebase zuerst einen neuen Branch.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout -b feat_kap_7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to a new branch &lt;span class="s1"&gt;&amp;#39;feat_kap_7&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Erstellen Sie nun eine neue Daten &lt;code&gt;kapitel_7.txt&lt;/code&gt; mit folgenden Inhalt und fügen Sie diese Datei zur Versionsverwaltung hinzu.&lt;/p&gt;
&lt;p&gt;Fügen Sie folgenden Inhalt der Datei hinzu und schreiben Sie die Version fest.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Der Ausgang der Geschichte wird angepasst ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wechseln Sie nun zurück zu dem &lt;code&gt;main&lt;/code&gt; Branch, um auch hier einige Änderungen vorzunehmen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Machen Sie nun folgende Änderungen in der Datei &lt;code&gt;kapitel_6.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Und es wurde endlich besser...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Historie sieht nun wie folgt aus (gekürzt):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cf10f7f &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Besser
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 67f77fa &lt;span class="o"&gt;(&lt;/span&gt;feat_kap_7&lt;span class="o"&gt;)&lt;/span&gt; Neue Geschichte
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 9a14335 Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 4a8d01e Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 654fae0 Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * a7d8ad7 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 602f965 Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; a915c82 Kapitel &lt;span class="m"&gt;6&lt;/span&gt; gestartet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 4893d66 Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 401162d Kapitel &lt;span class="m"&gt;1&lt;/span&gt; ausgearbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* ae2918a Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An den Graphen sehen wir, dass hier ein Merge zu keinem &amp;ldquo;Fast Merge&amp;rdquo; führen würde (keine lineare Historie), sondern einen &amp;ldquo;Merge&amp;rdquo;-Commit (wie bei der Zusammenführung des &lt;code&gt;feat_kap_5&lt;/code&gt; Branches). Das können wir nun mit einen Rebase verhindern. Wechseln Sie zuerst auf den &lt;code&gt;feat_kap_7&lt;/code&gt; branch. Dieser soll nun neue &amp;ldquo;Basis&amp;rdquo; bekommen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout feat_kap_7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;feat_kap_7&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun führen wir ein Rebase auf diesem Branch durch. D.h. der Branch bekommt eine neue Basis. Aktuell liegt diese auf dem Commit &lt;code&gt;Merge branch 'feat_kap_5'&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git rebase main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully rebased and updated refs/heads/feat_kap_7.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In dem Graphen sehen wir nun, dass die Basis sich von &lt;code&gt;Merge branch 'feat_kap_5'&lt;/code&gt; zu &lt;code&gt;Besser&lt;/code&gt; verschoben hat.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 874e90c &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; feat_kap_7&lt;span class="o"&gt;)&lt;/span&gt; Neue Geschichte
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 71c03a0 Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cf10f7f &lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt; Besser
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 4a8d01e &lt;span class="o"&gt;(&lt;/span&gt;origin/main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 654fae0 Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * a7d8ad7 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 602f965 Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; a915c82 Kapitel &lt;span class="m"&gt;6&lt;/span&gt; gestartet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 4893d66 Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 401162d Kapitel &lt;span class="m"&gt;1&lt;/span&gt; ausgearbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* ae2918a Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit diesen Graphen können wir den Branch &lt;code&gt;feat_kap_7&lt;/code&gt; relativ einfach über einen &amp;ldquo;Fast Merge&amp;rdquo; in unser &lt;code&gt;main&lt;/code&gt; Branch integrieren.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Switched to branch &lt;span class="s1"&gt;&amp;#39;main&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git merge feat_kap_7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updating cf10f7f..874e90c
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Fast-forward
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; kapitel_7.txt &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; ++
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;2&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_7.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git branch -d feat_kap_7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Deleted branch feat_kap_7 &lt;span class="o"&gt;(&lt;/span&gt;was 874e90c&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="konflikte-beim-rebase-lösen"&gt;Konflikte beim &lt;code&gt;rebase&lt;/code&gt; lösen&lt;/h2&gt;
&lt;p&gt;Genau wie beim &lt;code&gt;merge&lt;/code&gt; kann es auch bei &lt;code&gt;rebase&lt;/code&gt; zu Konflikten führen, die gelöst werden müssen. Im Gegensatz zu &lt;code&gt;merge&lt;/code&gt; können die Konflikte mehrmals vorkommen, praktisch bei jeder &amp;ldquo;Wiedergabe&amp;rdquo; (replay) eines Commits auf die neue Basis. Dabei stoppt das Rebase und erlaubt uns die Konflikte zu lösen (ähnlich wie bei &lt;code&gt;merge&lt;/code&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mit &lt;code&gt;git add&lt;/code&gt; markieren wir eine Datei mit dem Konflikt, dass der Konflikt beseitigt ist.&lt;/li&gt;
&lt;li&gt;Mit &lt;code&gt;git rebase --continue&lt;/code&gt; setzen wir das Rebase fort (wiedergeben den nächsten Commit auf die neue Basis).&lt;/li&gt;
&lt;li&gt;Mit &lt;code&gt;git rebase --abort&lt;/code&gt; können wir das Rebase abbrechen (ähnlich wie beim &lt;code&gt;merge&lt;/code&gt; während eines Konfliktes).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-orange-100 dark:bg-orange-900 border-orange-500"
data-callout="warning"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-orange-600 dark:text-orange-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0zM12 15.75h.007v.008H12z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Warnung&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Da ein &lt;code&gt;rebase&lt;/code&gt; die Historie verändert, sollte dieser nur auf den Commits durchgeführt werden, die noch nicht zu einem Zentralen git-Server synchronisiert wurden (oder nur auf Branches auf denen man allein arbeitet).&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Squash: Commits zusammenführen</title><link>https://kurse.richter.consulting/courses/git/squash/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/squash/</guid><description>&lt;h2 id="was-ist-squash"&gt;Was ist &lt;code&gt;squash&lt;/code&gt;&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;?&lt;/h2&gt;
&lt;p&gt;Ein Git Squash ermöglicht es, mehrere Commits zu einem einzelnen Commit zusammenzufassen. Dies ist besonders nützlich, um die Commit-Historie sauber zu halten. Dabei kan man &lt;code&gt;squash&lt;/code&gt; sowohl mit &lt;code&gt;rebase&lt;/code&gt; (aktueller Branch) als auch mit &lt;code&gt;merge&lt;/code&gt; nutzen.&lt;/p&gt;
&lt;h2 id="anwendung-mit-rebase"&gt;Anwendung mit &lt;code&gt;rebase&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Ein &lt;code&gt;rebase&lt;/code&gt; kann in einen interaktiven Modus durchgeführt werden (Parameter &lt;code&gt;-i&lt;/code&gt; oder &lt;code&gt;--interactive&lt;/code&gt;). Dabei werden alle betroffenen Commits, die &amp;ldquo;wiedergegeben&amp;rdquo; werden, in dem Texteditor angezeigt und können angepasst werden.&lt;/p&gt;
&lt;p&gt;Für &lt;code&gt;squash&lt;/code&gt; mit &lt;code&gt;rebase&lt;/code&gt; geben wir die Anzahl der Commits, die zusammengefasst werden sollen mit &lt;code&gt;HEAD-&amp;lt;n&amp;gt;&lt;/code&gt; an (die selbe Syntax, die wir bereits mit &lt;code&gt;diff&lt;/code&gt; gesehen haben, um Commits relativ anzusprechen). Wir wollen nun die letzten Beiden Commits unserer Historie zusammenfassen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 874e90c &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Neue Geschichte
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 71c03a0 Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cf10f7f Besser
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 4a8d01e &lt;span class="o"&gt;(&lt;/span&gt;origin/main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dazu führen wir das interaktive &lt;code&gt;rebase&lt;/code&gt; für die letzten 2 Commits durch.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git rebase -i HEAD~2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Darauf erscheint im Texteditor die Auflistung der betroffenen Commits (und ein Wenig Dokumentation dazu - mit &lt;code&gt;#&lt;/code&gt; auskommentiert):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick 71c03a0 Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick 874e90c Neue Geschichte
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Rebase cf10f7f..874e90c onto cf10f7f (2 commands)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Commands:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# p, pick &amp;lt;commit&amp;gt; = use commit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# f, fixup [-C | -c] &amp;lt;commit&amp;gt; = like &amp;#34;squash&amp;#34; but keep only the previous&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# commit&amp;#39;s log message, unless -C is used, in which case&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# keep only this commit&amp;#39;s message; -c is same as -C but&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# opens the editor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# x, exec &amp;lt;command&amp;gt; = run command (the rest of the line) using shell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# b, break = stop here (continue rebase later with &amp;#39;git rebase --continue&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# d, drop &amp;lt;commit&amp;gt; = remove commit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# l, label &amp;lt;label&amp;gt; = label current HEAD with a name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# t, reset &amp;lt;label&amp;gt; = reset HEAD to a label&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# m, merge [-C &amp;lt;commit&amp;gt; | -c &amp;lt;commit&amp;gt;] &amp;lt;label&amp;gt; [# &amp;lt;oneline&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# create a merge commit using the original merge commit&amp;#39;s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# message (or the oneline, if no original merge commit was&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# specified); use -c &amp;lt;commit&amp;gt; to reword the commit message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# u, update-ref &amp;lt;ref&amp;gt; = track a placeholder for the &amp;lt;ref&amp;gt; to be updated&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# to this position in the new commits. The &amp;lt;ref&amp;gt; is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Relevant sind nur die ersten beiden Zeilen. Jede Zeile (Commit), die mit &lt;code&gt;pick&lt;/code&gt; beginnt, wird im Original übernommen - wird also wieder zu einem Commit. Ändern Sie die Commits, die Zusammengefasst werden sollen von &lt;code&gt;pick&lt;/code&gt; zu &lt;code&gt;squash&lt;/code&gt; (in unserem Beispiel also den zweiten Commit).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pick 71c03a0 Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;squash 874e90c Neue Geschichte
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;Unter Linux/macOS können Sie den &amp;ldquo;vi(m)&amp;quot;-Editor mit &lt;code&gt;Esc&lt;/code&gt;-Taste und dann mit &lt;code&gt;:wq&lt;/code&gt; (write and quit) verlassen.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nun können Sie auch das finale Commit bearbeiten, wenn Sie es möchten:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# This is a combination of 2 commits.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# This is the 1st commit message:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# This is the commit message #2:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Neue Geschichte
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Please enter the commit message for your changes. Lines starting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# with &amp;#39;#&amp;#39; will be ignored, and an empty message aborts the commit.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Date: Mon Apr 7 08:01:30 2025 +0200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# interactive rebase in progress; onto cf10f7f&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Last commands done (2 commands done):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# pick 71c03a0 Start mit Kapitel 7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# squash 874e90c Neue Geschichte&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# No commands remaining.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# You are currently rebasing branch &amp;#39;main&amp;#39; on &amp;#39;cf10f7f&amp;#39;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Changes to be committed:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# new file: kapitel_7.txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit dem Verlassen des Commit-Message Editors, wird die Historie umgeschrieben.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git rebase -i HEAD~2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;detached HEAD a93f4f8&lt;span class="o"&gt;]&lt;/span&gt; Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Date: Mon Apr &lt;span class="m"&gt;7&lt;/span&gt; 08:01:30 &lt;span class="m"&gt;2025&lt;/span&gt; +0200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;2&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_7.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Successfully rebased and updated refs/heads/main.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* a93f4f8 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Start mit Kapitel &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cf10f7f Besser
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 4a8d01e &lt;span class="o"&gt;(&lt;/span&gt;origin/main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="letzten-commit-anpassen"&gt;Letzten Commit anpassen&lt;/h2&gt;
&lt;p&gt;Sollten nur die letzten Änderungen (bereits mit &lt;code&gt;git add&lt;/code&gt; in das Staging-Bereich hinzugefügt, aber noch kein Commit erstellt) in das letzte Commit reinfließen, geht es noch ein wenig einfacher. Dazu kann das &lt;code&gt;--amend&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; Parameter vom &lt;code&gt;commit&lt;/code&gt;-Command genutzt werden.&lt;/p&gt;
&lt;p&gt;Machen Sie folgende Änderung in &lt;code&gt;kapitel_7.txt&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Kapitel 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Der Ausgang der Geschichte wird angepasst ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Und manchmal zusammengeführt...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fügen Sie die Änderung zum Staging Bereich mit &lt;code&gt;git add&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git add kapitel_7.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nun können wir mit &lt;code&gt;--amend&lt;/code&gt; diese Änderung zum letzten Commit hinzufügen. Wenn wir die Message des letzten Commits nicht ändern wollen, können wird den Parameter &lt;code&gt;--no-edit&lt;/code&gt; anhängen, oder mit &lt;code&gt;-m&lt;/code&gt; eine neue Message angeben.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git commit --amend -m &lt;span class="s2"&gt;&amp;#34;Kapitel 7 fängt an&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;main 28087f7&lt;span class="o"&gt;]&lt;/span&gt; Kapitel &lt;span class="m"&gt;7&lt;/span&gt; fängt an
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Date: Mon Apr &lt;span class="m"&gt;7&lt;/span&gt; 08:01:30 &lt;span class="m"&gt;2025&lt;/span&gt; +0200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1&lt;/span&gt; file changed, &lt;span class="m"&gt;3&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; create mode &lt;span class="m"&gt;100644&lt;/span&gt; kapitel_7.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit dem Status sehen wir nun, dass keine Änderungen mehr vorliegen und and der Historie den geänderten letzten Commit (anderer Hash-Wert und Message).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git status
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;On branch main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your branch is ahead of &lt;span class="s1"&gt;&amp;#39;origin/main&amp;#39;&lt;/span&gt; by &lt;span class="m"&gt;2&lt;/span&gt; commits.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;&amp;#34;git push&amp;#34;&lt;/span&gt; to publish your &lt;span class="nb"&gt;local&lt;/span&gt; commits&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nothing to commit, working tree clean
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 28087f7 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;7&lt;/span&gt; fängt an
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cf10f7f Besser
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 4a8d01e &lt;span class="o"&gt;(&lt;/span&gt;origin/main&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-orange-100 dark:bg-orange-900 border-orange-500"
data-callout="warning"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-orange-600 dark:text-orange-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0zM12 15.75h.007v.008H12z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Warnung&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Da sowohl &lt;code&gt;rebase -i&lt;/code&gt; als auch &lt;code&gt;commit --amend&lt;/code&gt; die Historie verändert, sollte dieser nur auf den Commits durchgeführt werden, die noch nicht zu einem Zentralen git-Server synchronisiert wurden (oder nur auf Branches auf denen man allein arbeitet).&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;
&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Benannte Versionen mit Tags</title><link>https://kurse.richter.consulting/courses/git/tags/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/tags/</guid><description>&lt;p&gt;Wir Menschen sind nicht dazu geeignet Hash-Werte zu merken. Das ist aber manchmal notwendig, um zu einem bestimmten Stand in der Geschichte zurückkehren zu können. Hier helfen und sogenannte &lt;code&gt;Tags&lt;/code&gt;, die an ein Commit angehängt werden können. Wir können diese als eine kleine Notiz an einem Commit vorstellen.&lt;/p&gt;
&lt;p&gt;Git unterstützt dabei zwei Arten von Tags.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Leichtgewichtige Tags, die nur aus dem Tag selbst bestehen. Es ist am Ende ein einfacher Zeiger auf den Commit, wie bei Branches, der sich aber nicht bewegt.&lt;/li&gt;
&lt;li&gt;Annotierte Tags, die neben dem Tag selbst noch weitere Informationen tragen, wie eine zusätzliche Nachricht.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="leichtgewichtiger-tag"&gt;Leichtgewichtiger Tag&lt;/h2&gt;
&lt;p&gt;Legen wir zuerst einen leichtgewichtigen Tag an, der auf den &lt;em&gt;letzten&lt;/em&gt; Commit zeigt. Dazu nutzen wir das &lt;code&gt;git tag&lt;/code&gt; Befehl mit dem Namen des Tags.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git tag &lt;span class="s1"&gt;&amp;#39;kap-05&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 7a000b4 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main, tag: kap-05&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 408a803 &lt;span class="o"&gt;(&lt;/span&gt;feat_kap_5&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git tag
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kap-05
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mit &lt;code&gt;git tag&lt;/code&gt; können wir alle Tags der Repositories auflisten lassen. Mit &lt;code&gt;git show&lt;/code&gt; können wir die Informationen zu einem Commit, oder Tag aufrufen. Bei leichtgewichtigen erscheinen dabei keine zusätzlichen Informationen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git show kap-05
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;commit 7a000b46cdd307aea91cc0e151fa6b7ff7daad78 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main, tag: kap-05&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Merge: 618450e 408a803
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Author: Eugen &lt;span class="o"&gt;[&lt;/span&gt;WebDucer&lt;span class="o"&gt;]&lt;/span&gt; Richter &amp;lt;github@webducer.de&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Mon May &lt;span class="m"&gt;2&lt;/span&gt; 06:56:58 &lt;span class="m"&gt;2022&lt;/span&gt; +0200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;diff --cc kapitel_4.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="annotierter-tag"&gt;Annotierter Tag&lt;/h2&gt;
&lt;p&gt;Nun legen wir einen annotierten Tag an, der neben der Nachricht, auch auf einen bestimmten Commit angehängt wird, nicht den aktuellen. Dazu wird der Parameter &lt;code&gt;-a&lt;/code&gt; (für annotiert) und &lt;code&gt;-m&lt;/code&gt; (für Message) genutzt. Der Commit auf den wir uns beziehen, wird als Hash (oder &lt;code&gt;HEAD&lt;/code&gt;-Relative-Referenz, wie bei &lt;code&gt;diff&lt;/code&gt;) mit angegeben.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git tag -a &lt;span class="s1"&gt;&amp;#39;kap-04&amp;#39;&lt;/span&gt; e779542 -m &lt;span class="s2"&gt;&amp;#34;Kapitel 4 über Tag&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;repo_1$ git pl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* 7a000b4 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; main, tag: kap-05&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;feat_kap_5&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 408a803 &lt;span class="o"&gt;(&lt;/span&gt;feat_kap_5&lt;span class="o"&gt;)&lt;/span&gt; Kapitel &lt;span class="m"&gt;4&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 47c1c6d Kapitel &lt;span class="m"&gt;1&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; * 1b28574 Fahrt im Zug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 618450e Kapitel &lt;span class="m"&gt;6&lt;/span&gt; gestartet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 54a8d9a Kapitel &lt;span class="m"&gt;2&lt;/span&gt; überarbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* &lt;span class="p"&gt;|&lt;/span&gt; 0b1ad44 Kapitel &lt;span class="m"&gt;1&lt;/span&gt; ausgearbeitet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* e779542 &lt;span class="o"&gt;(&lt;/span&gt;tag: kap-04&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;&amp;#39;develop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_repo_1$ git show kap-04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tag kap-04
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tagger: Eugen &lt;span class="o"&gt;[&lt;/span&gt;WebDucer&lt;span class="o"&gt;]&lt;/span&gt; Richter &amp;lt;github@webducer.de&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Mon May &lt;span class="m"&gt;2&lt;/span&gt; 07:13:57 &lt;span class="m"&gt;2022&lt;/span&gt; +0200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kapitel &lt;span class="m"&gt;4&lt;/span&gt; über Tag
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;commit e7795427bf9235f54e8fc3cc73b0fa4f43678373 &lt;span class="o"&gt;(&lt;/span&gt;tag: kap-04&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Merge: 10eabc1 aac4d8b
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Author: Eugen &lt;span class="o"&gt;[&lt;/span&gt;WebDucer&lt;span class="o"&gt;]&lt;/span&gt; Richter &amp;lt;github@webducer.de&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Date: Mon May &lt;span class="m"&gt;2&lt;/span&gt; 05:46:44 &lt;span class="m"&gt;2022&lt;/span&gt; +0200
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bei &lt;code&gt;git show&lt;/code&gt; sehen wir nun neben den Informationen zu dem Commit selbst (fängt mit &lt;code&gt;commit e7794&lt;/code&gt; an) auch die Informationen zu dem Tag (es können auch mehrere sein) oberhalb von diesem. Hier werden neben der Nachricht auch die Informationen zu dem Ersteller des Tags angezeigt.&lt;/p&gt;</description></item><item><title>Oft benötigte Commands</title><link>https://kurse.richter.consulting/courses/container/commands/</link><pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/commands/</guid><description>&lt;h2 id="docker-run"&gt;&lt;code&gt;docker run&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M73.8 50.8h11.3v11.5h5.7c2.6 0 5.3-.5 7.8-1.3c1.2-.4 2.6-1 3.8-1.7c-1.6-2.1-2.4-4.7-2.6-7.3c-.3-3.5.4-8.1 2.8-10.8l1.2-1.4l1.4 1.1c3.6 2.9 6.5 6.8 7.1 11.4c4.3-1.3 9.3-1 13.1 1.2l1.5.9l-.8 1.6c-3.2 6.2-9.9 8.2-16.4 7.8c-9.8 24.3-31 35.8-56.8 35.8c-13.3 0-25.5-5-32.5-16.8l-.1-.2l-1-2.1c-2.4-5.2-3.1-10.9-2.6-16.6l.2-1.7h9.6V50.8h11.3V39.6h22.5V28.3h13.5z" clip-rule="evenodd"/&gt;&lt;path fill="#00aada" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7H18.6c-.6 6.2.5 11.9 3 16.8l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5 1.1-8.3 1.3h-.6c-1.3.1-2.7.1-4.2.1c-1.6 0-3.1 0-4.9-.1c6 6.8 15.4 10.8 27.2 10.8c25 0 46.2-11.1 55.5-35.9c6.7.7 13.1-1 16-6.7c-4.5-2.7-10.5-1.8-13.9-.1"/&gt;&lt;path fill="#28b8eb" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7h-68c-.3 9.5 3.2 16.7 9.5 21c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4l-.1-.1c8.5 4.4 20.8 4.3 35-1.1c15.8-6.1 30.6-17.7 40.9-30.9c-.2.1-.4.1-.5.2"/&gt;&lt;path fill="#028bb8" d="M18.7 71.8c.4 3.3 1.4 6.4 2.9 9.3l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4h-.4c-1.3.1-2.7.1-4.1.1c-1.6 0-3.2 0-4.9-.1c6 6.8 15.5 10.8 27.3 10.8c21.4 0 40-8.1 50.8-26H18.7z"/&gt;&lt;path fill="#019bc6" d="M23.5 71.8c1.3 5.8 4.3 10.4 8.8 13.5c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.6 1.4c8.5 4.4 20.8 4.3 34.9-1.1c8.5-3.3 16.8-8.2 24.2-14.1z"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M28.4 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3-12h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M39.6 52.7h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M50.9 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M50.9 41.5h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3.1 10.4H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M62.2 41.5H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M62.2 30.2H72V40h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M73.5 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#d4eef1" fill-rule="evenodd" d="M48.8 78.3c1.5 0 2.7 1.2 2.7 2.7s-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7s1.2-2.7 2.7-2.7" clip-rule="evenodd"/&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M48.8 79.1c.2 0 .5 0 .7.1c-.2.1-.4.4-.4.7c0 .4.4.8.8.8c.3 0 .6-.2.7-.4c.1.2.1.5.1.7c0 1.1-.9 1.9-1.9 1.9c-1.1 0-1.9-.9-1.9-1.9s.8-1.9 1.9-1.9M1.1 72.8h125.4c-2.7-.7-8.6-1.6-7.7-5.2c-5 5.7-16.9 4-20 1.2c-3.4 4.9-23 3-24.3-.8c-4.2 5-17.3 5-21.5 0c-1.4 3.8-21 5.7-24.3.8c-3 2.8-15 4.5-20-1.2c1.1 3.5-4.9 4.5-7.6 5.2" clip-rule="evenodd"/&gt;&lt;path fill="#bfdbe0" d="M56 97.8c-6.7-3.2-10.3-7.5-12.4-12.2c-2.5.7-5.5 1.2-8.9 1.4c-1.3.1-2.7.1-4.1.1c-1.7 0-3.4 0-5.2-.1c6 6 13.6 10.7 27.5 10.8z"/&gt;&lt;path fill="#d4eef1" d="M46.1 89.9c-.9-1.3-1.8-2.8-2.5-4.3c-2.5.7-5.5 1.2-8.9 1.4c2.3 1.2 5.7 2.4 11.4 2.9"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Startet ein neues Container basierend auf den übergebenen Image. Abhängign von den Fähigkeiten des Images, können zusätliche Parameter übergeben / genutzt werden.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="wichtige-parameter"&gt;Wichtige Parameter&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--name&lt;/code&gt; Name des Containers. Wenn dieser nicht mitgegeben wird, wir der Name von der Runtime vergeben.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d&lt;/code&gt; oder &lt;code&gt;--detach&lt;/code&gt; Detatched. D.h. die Runtime startet den Container im Hintergrund, so dass das Terminal für weitere Eingaben zur Verfügung steht.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-e&lt;/code&gt; oder &lt;code&gt;--env&lt;/code&gt; Setzen der Umgebungsvariablen innnerhalb des Containers (kann auch mehrfach genutzt werden, um mehrere Umgebungsvariablen zu setzen).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p&lt;/code&gt; oder &lt;code&gt;--publish&lt;/code&gt; Port Publishing. Gibt an welcher Container-Port zu welchen Host-Port umgeleitet werden soll.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-v&lt;/code&gt; oder &lt;code&gt;--volume&lt;/code&gt; Mapping für Speicher (Dateien oder Orner)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-rm&lt;/code&gt; Starte einen neuen Container. Somald dieser beendet wird, wird dieser auch gleich gelöscht (praktsich für &amp;ldquo;ein Mal ausführen&amp;rdquo; Container).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-it&lt;/code&gt; Kombination aus &lt;code&gt;-i&lt;/code&gt; (&lt;code&gt;--interactive&lt;/code&gt;) und &lt;code&gt;-t&lt;/code&gt; (&lt;code&gt;--tty&lt;/code&gt;) und erlaubt interaktiv in den Container &amp;ldquo;reinzugehen&amp;rdquo;, um dessen Inhalt zum Beispiel zu untersuchen&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --name my-homepage &lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p 1080:8080 &lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e &lt;span class="nv"&gt;NGINX_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8080&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -e &lt;span class="nv"&gt;NGINX_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-homepage.io&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /www/website:/usr/share/nginx/html:ro &lt;span class="se"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-start"&gt;&lt;code&gt;docker start&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M73.8 50.8h11.3v11.5h5.7c2.6 0 5.3-.5 7.8-1.3c1.2-.4 2.6-1 3.8-1.7c-1.6-2.1-2.4-4.7-2.6-7.3c-.3-3.5.4-8.1 2.8-10.8l1.2-1.4l1.4 1.1c3.6 2.9 6.5 6.8 7.1 11.4c4.3-1.3 9.3-1 13.1 1.2l1.5.9l-.8 1.6c-3.2 6.2-9.9 8.2-16.4 7.8c-9.8 24.3-31 35.8-56.8 35.8c-13.3 0-25.5-5-32.5-16.8l-.1-.2l-1-2.1c-2.4-5.2-3.1-10.9-2.6-16.6l.2-1.7h9.6V50.8h11.3V39.6h22.5V28.3h13.5z" clip-rule="evenodd"/&gt;&lt;path fill="#00aada" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7H18.6c-.6 6.2.5 11.9 3 16.8l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5 1.1-8.3 1.3h-.6c-1.3.1-2.7.1-4.2.1c-1.6 0-3.1 0-4.9-.1c6 6.8 15.4 10.8 27.2 10.8c25 0 46.2-11.1 55.5-35.9c6.7.7 13.1-1 16-6.7c-4.5-2.7-10.5-1.8-13.9-.1"/&gt;&lt;path fill="#28b8eb" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7h-68c-.3 9.5 3.2 16.7 9.5 21c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4l-.1-.1c8.5 4.4 20.8 4.3 35-1.1c15.8-6.1 30.6-17.7 40.9-30.9c-.2.1-.4.1-.5.2"/&gt;&lt;path fill="#028bb8" d="M18.7 71.8c.4 3.3 1.4 6.4 2.9 9.3l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4h-.4c-1.3.1-2.7.1-4.1.1c-1.6 0-3.2 0-4.9-.1c6 6.8 15.5 10.8 27.3 10.8c21.4 0 40-8.1 50.8-26H18.7z"/&gt;&lt;path fill="#019bc6" d="M23.5 71.8c1.3 5.8 4.3 10.4 8.8 13.5c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.6 1.4c8.5 4.4 20.8 4.3 34.9-1.1c8.5-3.3 16.8-8.2 24.2-14.1z"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M28.4 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3-12h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M39.6 52.7h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M50.9 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M50.9 41.5h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3.1 10.4H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M62.2 41.5H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M62.2 30.2H72V40h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M73.5 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#d4eef1" fill-rule="evenodd" d="M48.8 78.3c1.5 0 2.7 1.2 2.7 2.7s-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7s1.2-2.7 2.7-2.7" clip-rule="evenodd"/&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M48.8 79.1c.2 0 .5 0 .7.1c-.2.1-.4.4-.4.7c0 .4.4.8.8.8c.3 0 .6-.2.7-.4c.1.2.1.5.1.7c0 1.1-.9 1.9-1.9 1.9c-1.1 0-1.9-.9-1.9-1.9s.8-1.9 1.9-1.9M1.1 72.8h125.4c-2.7-.7-8.6-1.6-7.7-5.2c-5 5.7-16.9 4-20 1.2c-3.4 4.9-23 3-24.3-.8c-4.2 5-17.3 5-21.5 0c-1.4 3.8-21 5.7-24.3.8c-3 2.8-15 4.5-20-1.2c1.1 3.5-4.9 4.5-7.6 5.2" clip-rule="evenodd"/&gt;&lt;path fill="#bfdbe0" d="M56 97.8c-6.7-3.2-10.3-7.5-12.4-12.2c-2.5.7-5.5 1.2-8.9 1.4c-1.3.1-2.7.1-4.1.1c-1.7 0-3.4 0-5.2-.1c6 6 13.6 10.7 27.5 10.8z"/&gt;&lt;path fill="#d4eef1" d="M46.1 89.9c-.9-1.3-1.8-2.8-2.5-4.3c-2.5.7-5.5 1.2-8.9 1.4c2.3 1.2 5.7 2.4 11.4 2.9"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Starten einen bereits vorhandenen Container. Als Parameter wird der Name oder die ID des Containers akzeptiert.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker start my-homepage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="docker-stop"&gt;&lt;code&gt;docker stop&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M73.8 50.8h11.3v11.5h5.7c2.6 0 5.3-.5 7.8-1.3c1.2-.4 2.6-1 3.8-1.7c-1.6-2.1-2.4-4.7-2.6-7.3c-.3-3.5.4-8.1 2.8-10.8l1.2-1.4l1.4 1.1c3.6 2.9 6.5 6.8 7.1 11.4c4.3-1.3 9.3-1 13.1 1.2l1.5.9l-.8 1.6c-3.2 6.2-9.9 8.2-16.4 7.8c-9.8 24.3-31 35.8-56.8 35.8c-13.3 0-25.5-5-32.5-16.8l-.1-.2l-1-2.1c-2.4-5.2-3.1-10.9-2.6-16.6l.2-1.7h9.6V50.8h11.3V39.6h22.5V28.3h13.5z" clip-rule="evenodd"/&gt;&lt;path fill="#00aada" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7H18.6c-.6 6.2.5 11.9 3 16.8l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5 1.1-8.3 1.3h-.6c-1.3.1-2.7.1-4.2.1c-1.6 0-3.1 0-4.9-.1c6 6.8 15.4 10.8 27.2 10.8c25 0 46.2-11.1 55.5-35.9c6.7.7 13.1-1 16-6.7c-4.5-2.7-10.5-1.8-13.9-.1"/&gt;&lt;path fill="#28b8eb" d="M110.4 55.1c.8-5.9-3.6-10.5-6.4-12.7c-3.1 3.6-3.6 13.2 1.3 17.2c-2.8 2.4-8.5 4.7-14.5 4.7h-68c-.3 9.5 3.2 16.7 9.5 21c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4l-.1-.1c8.5 4.4 20.8 4.3 35-1.1c15.8-6.1 30.6-17.7 40.9-30.9c-.2.1-.4.1-.5.2"/&gt;&lt;path fill="#028bb8" d="M18.7 71.8c.4 3.3 1.4 6.4 2.9 9.3l.8 1.5c.5.9 1.1 1.7 1.7 2.6c3 .2 5.7.3 8.2.2c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.5 1.4h-.4c-1.3.1-2.7.1-4.1.1c-1.6 0-3.2 0-4.9-.1c6 6.8 15.5 10.8 27.3 10.8c21.4 0 40-8.1 50.8-26H18.7z"/&gt;&lt;path fill="#019bc6" d="M23.5 71.8c1.3 5.8 4.3 10.4 8.8 13.5c4.9-.1 8.9-.7 12-1.7c.5-.2.9.1 1.1.5c.2.5-.1.9-.5 1.1c-.4.1-.8.3-1.3.4c-2.4.7-5.2 1.2-8.6 1.4c8.5 4.4 20.8 4.3 34.9-1.1c8.5-3.3 16.8-8.2 24.2-14.1z"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M28.4 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3-12h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M39.6 52.7h9.8v9.8h-9.8zm.9.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M50.9 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M50.9 41.5h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm3.1 10.4H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M62.2 41.5H72v9.8h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#23c2ee" fill-rule="evenodd" d="M62.2 30.2H72V40h-9.8zm.8.8h.8v8.1H63zm1.5 0h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#00acd3" fill-rule="evenodd" d="M73.5 52.7h9.8v9.8h-9.8zm.8.8h.8v8.1h-.8zm1.4 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8zm1.5 0h.8v8.1h-.8z" clip-rule="evenodd"/&gt;&lt;path fill="#d4eef1" fill-rule="evenodd" d="M48.8 78.3c1.5 0 2.7 1.2 2.7 2.7s-1.2 2.7-2.7 2.7s-2.7-1.2-2.7-2.7s1.2-2.7 2.7-2.7" clip-rule="evenodd"/&gt;&lt;path fill="#3a4d54" fill-rule="evenodd" d="M48.8 79.1c.2 0 .5 0 .7.1c-.2.1-.4.4-.4.7c0 .4.4.8.8.8c.3 0 .6-.2.7-.4c.1.2.1.5.1.7c0 1.1-.9 1.9-1.9 1.9c-1.1 0-1.9-.9-1.9-1.9s.8-1.9 1.9-1.9M1.1 72.8h125.4c-2.7-.7-8.6-1.6-7.7-5.2c-5 5.7-16.9 4-20 1.2c-3.4 4.9-23 3-24.3-.8c-4.2 5-17.3 5-21.5 0c-1.4 3.8-21 5.7-24.3.8c-3 2.8-15 4.5-20-1.2c1.1 3.5-4.9 4.5-7.6 5.2" clip-rule="evenodd"/&gt;&lt;path fill="#bfdbe0" d="M56 97.8c-6.7-3.2-10.3-7.5-12.4-12.2c-2.5.7-5.5 1.2-8.9 1.4c-1.3.1-2.7.1-4.1.1c-1.7 0-3.4 0-5.2-.1c6 6 13.6 10.7 27.5 10.8z"/&gt;&lt;path fill="#d4eef1" d="M46.1 89.9c-.9-1.3-1.8-2.8-2.5-4.3c-2.5.7-5.5 1.2-8.9 1.4c2.3 1.2 5.7 2.4 11.4 2.9"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Stopt einen bereits vorhandenen und laufenden Container. Als Parameter wird der Name oder die ID des Containers akzeptiert.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker stop my-homepage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Glossar</title><link>https://kurse.richter.consulting/courses/container/glossar/</link><pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/glossar/</guid><description>&lt;h2 id="container"&gt;Container&lt;/h2&gt;
&lt;p&gt;Ein Container ist eine Laufzeitinstanz eines
.&lt;/p&gt;
&lt;p&gt;Ein Docker-Container besteht aus&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Einem Docker-Abbild&lt;/li&gt;
&lt;li&gt;einer Ausführungsumgebung&lt;/li&gt;
&lt;li&gt;Einem Standardsatz von Anweisungen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Das Konzept ist von den Schiffscontainern abgeleitet, die einen Standard für den weltweiten Versand von Waren definieren. OCI definiert einen Standard für den Versand von Software.&lt;/p&gt;
&lt;h2 id="image--container-image"&gt;Image / Container-Image&lt;/h2&gt;
&lt;p&gt;Container-Images sind die Grundlage von Containern. Ein Image ist eine geordnete Sammlung von Dateisystemänderungen und den Ausführungsparametern zur Verwendung innerhalb einer Container-Laufzeit. Ein Image enthält in der Regel eine Vereinigung von übereinander gestapelten Dateisystemen.&lt;/p&gt;
&lt;h2 id="container-registry"&gt;Container Registry&lt;/h2&gt;
&lt;p&gt;Container Registry ist ein zentraler Speicherort für die fertig gebauten Images.&lt;/p&gt;
&lt;h2 id="repository"&gt;Repository&lt;/h2&gt;
&lt;p&gt;Ein Repository ist ein Satz von Container-Images (meist derselben Software). Ein Repository kann freigegeben werden, indem es auf einen Registry-Server gepusht wird. Die verschiedenen Images im Repository können mit Tags (Versionen) gekennzeichnet werden.&lt;/p&gt;</description></item><item><title>Weiterführende Links und Ressourcen</title><link>https://kurse.richter.consulting/courses/container/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/container/links/</guid><description>&lt;h2 id="projektressourcen"&gt;Projektressourcen&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;g fill="#181616"&gt;&lt;path fill-rule="evenodd" d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388c0 26.682 17.303 49.317 41.297 57.303c3.017.56 4.125-1.31 4.125-2.905c0-1.44-.056-6.197-.082-11.243c-16.8 3.653-20.345-7.125-20.345-7.125c-2.747-6.98-6.705-8.836-6.705-8.836c-5.48-3.748.413-3.67.413-3.67c6.063.425 9.257 6.223 9.257 6.223c5.386 9.23 14.127 6.562 17.573 5.02c.542-3.903 2.107-6.568 3.834-8.076c-13.413-1.525-27.514-6.704-27.514-29.843c0-6.593 2.36-11.98 6.223-16.21c-.628-1.52-2.695-7.662.584-15.98c0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033c11.526-7.813 16.59-6.19 16.59-6.19c3.287 8.317 1.22 14.46.593 15.98c3.872 4.23 6.215 9.617 6.215 16.21c0 23.194-14.127 28.3-27.574 29.796c2.167 1.874 4.097 5.55 4.097 11.183c0 8.08-.07 14.583-.07 16.572c0 1.607 1.088 3.49 4.148 2.897c23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z" clip-rule="evenodd"/&gt;&lt;path d="M26.484 91.806c-.133.3-.605.39-1.035.185c-.44-.196-.685-.605-.543-.906c.13-.31.603-.395 1.04-.188c.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28c-.396-.42-.47-.983-.177-1.254c.298-.266.844-.14 1.24.28c.394.426.472.984.17 1.255zm2.382 3.477c-.37.258-.976.017-1.35-.52c-.37-.538-.37-1.183.01-1.44c.373-.258.97-.025 1.35.507c.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23c-.527-.487-.674-1.18-.343-1.544c.336-.366 1.045-.264 1.564.23c.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486c-.683-.207-1.13-.76-.99-1.238c.14-.477.823-.7 1.512-.485c.683.206 1.13.756.988 1.237m4.943.361c.017.498-.563.91-1.28.92c-.723.017-1.308-.387-1.315-.877c0-.503.568-.91 1.29-.924c.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117c-.7.13-1.35-.172-1.44-.653c-.086-.498.422-.997 1.122-1.126c.714-.123 1.354.17 1.444.663zm0 0"/&gt;&lt;/g&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;g fill="#623697"&gt;&lt;path d="M61.195 0h4.953c12.918.535 25.688 4.89 36.043 12.676c9.809 7.289 17.473 17.437 21.727 28.906c2.441 6.387 3.664 13.18 4.082 19.992v4.211c-.414 11.293-3.664 22.52-9.73 32.082c-6.801 10.895-16.922 19.73-28.727 24.828A64.4 64.4 0 0 1 65.082 128h-2.144c-11.735-.191-23.41-3.66-33.297-9.992c-11.196-7.113-20.114-17.785-25.028-30.117C1.891 81.19.441 74.02 0 66.812v-4.957c.504-14.39 5.953-28.609 15.41-39.496C23.168 13.31 33.5 6.48 44.887 2.937C50.172 1.27 55.676.41 61.195 0M25.191 37.523c-.03 12.153-.011 24.305-.011 36.454c1.43.011 2.86.011 4.293.011c-.075-10.433.101-20.863-.106-31.293c.48.907.918 1.84 1.465 2.707C37.035 54.91 43.105 64.5 49.309 74q2.607-.035 5.214.004c-.003-12.16-.007-24.32.004-36.48a308 308 0 0 0-4.25-.012c.075 10.32-.136 20.64.125 30.949c-6.507-10.352-13.101-20.645-19.695-30.945a371 371 0 0 0-5.516.007m38.844-.011c-.129 12.16-.004 24.32-.047 36.476c6.469-.015 12.938.024 19.41-.02a83 83 0 0 1 .024-3.952c-5.012-.016-10.027.007-15.043-.02c-.074-4.21-.004-8.426-.04-12.637c4.395-.078 8.79.012 13.18-.047c-.011-1.277-.011-2.554-.019-3.832c-4.387.141-8.773-.054-13.164.012q.019-6.035.02-12.078c4.699 0 9.398-.02 14.093.012c-.008-1.301 0-2.606.016-3.906c-6.145-.016-12.29-.008-18.43-.008m22.602.054c.004 1.266.004 2.528.008 3.79c3.488-.04 6.972.109 10.46.035c-.023 10.863.004 21.718-.011 32.574c1.46.043 2.93.035 4.39-.09c-.12-5.992.118-11.988-.156-17.977c.067-2.699-.07-5.394.117-8.09c.106-2.14-.277-4.277-.035-6.417c3.516.047 7.035.015 10.55.015a60 60 0 0 1 .075-3.832c-8.469-.105-16.937-.094-25.398-.008M13.55 69.094c-1.977.91-2.106 4.023-.149 5.027c1.72 1.18 4.305-.371 4.227-2.41c.133-2.004-2.29-3.688-4.078-2.617m29.23 15.289c-4.277 3.469-4.226 11.195.5 14.25c2.668 1.695 6.102 1.344 8.922.215q.017-.93.05-1.86c-2.671 1.395-6.41 1.68-8.675-.61c-2.965-3.237-2.297-9.269 1.613-11.476c2.211-1.164 4.907-.824 7.086.239c-.007-.66-.004-1.32 0-1.98c-3.097-1.099-6.922-1.04-9.496 1.222m17.207 2.71c-1.89.22-3.758 1.22-4.633 2.966c-1.253 2.496-1.109 5.867.864 7.96c2.035 2.297 5.945 2.32 8.18.297c2.425-2.308 2.699-6.468.757-9.164c-1.148-1.629-3.273-2.183-5.168-2.058m17.887 2.722c-1.66 2.883-1.332 7.25 1.598 9.211c2.183 1.22 4.933.832 7.074-.308q-.008-.927.031-1.848c-1.687 1.07-3.937 1.856-5.812.777c-1.309-.722-1.704-2.257-1.914-3.625c2.875-.039 5.746-.082 8.625-.074c-.075-1.828-.118-3.894-1.45-5.308c-2.199-2.43-6.644-1.657-8.152 1.175M69.46 87.48v12.008q.98-.001 1.973.004c.023-2.195-.04-4.394.023-6.594c.016-1.27.527-2.558 1.484-3.414c.801-.605 1.883-.27 2.801-.246q-.018-.954-.023-1.902c-1.793-.398-3.336.652-4.242 2.117c-.02-.633-.04-1.266-.051-1.894q-.986-.037-1.965-.079m0 0"/&gt;&lt;path d="M58.758 89.223c1.652-.805 4.023-.41 4.945 1.3c1.05 1.887 1.027 4.383-.137 6.211c-1.52 2.286-5.527 1.786-6.523-.742c-1.008-2.258-.617-5.484 1.715-6.77zm20.282 3.191c.046-1.574 1.144-3.137 2.726-3.48c.976-.164 2.097.007 2.773.793c.672.714.813 1.714.98 2.64c-2.16.012-4.32-.031-6.48.047zm0 0"/&gt;&lt;/g&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="weiterführende-ressourcen"&gt;Weiterführende Ressourcen&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Links</title><link>https://kurse.richter.consulting/courses/git/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kurse.richter.consulting/courses/git/links/</guid><description>&lt;h2 id="allgemein"&gt;Allgemein&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#f34f29" d="M124.737 58.378L69.621 3.264c-3.172-3.174-8.32-3.174-11.497 0L46.68 14.71l14.518 14.518c3.375-1.139 7.243-.375 9.932 2.314c2.703 2.706 3.461 6.607 2.294 9.993l13.992 13.993c3.385-1.167 7.292-.413 9.994 2.295c3.78 3.777 3.78 9.9 0 13.679a9.673 9.673 0 0 1-13.683 0a9.68 9.68 0 0 1-2.105-10.521L68.574 47.933l-.002 34.341a9.7 9.7 0 0 1 2.559 1.828c3.778 3.777 3.778 9.898 0 13.683c-3.779 3.777-9.904 3.777-13.679 0c-3.778-3.784-3.778-9.905 0-13.683a9.7 9.7 0 0 1 3.167-2.11V47.333a9.6 9.6 0 0 1-3.167-2.111c-2.862-2.86-3.551-7.06-2.083-10.576L41.056 20.333L3.264 58.123a8.133 8.133 0 0 0 0 11.5l55.117 55.114c3.174 3.174 8.32 3.174 11.499 0l54.858-54.858a8.135 8.135 0 0 0-.001-11.501"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" fill="currentColor" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"&gt;&lt;path d="M480-280q-73 0-127.5-45.5T284-440H80v-80h204q14-69 68.5-114.5T480-680q73 0 127.5 45.5T676-520h204v80H676q-14 69-68.5 114.5T480-280Zm0-80q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bücher"&gt;Bücher&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a9 9 0 0 1 7.843 4.582M12 3a9 9 0 0 0-7.843 4.582m15.686 0A11.95 11.95 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.96 8.96 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.9 17.9 0 0 1 12 16.5a17.9 17.9 0 0 1-8.716-2.247m0 0A9 9 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="currentColor"&gt;&lt;!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--&gt;&lt;path d="M353.7 226.7C305 228.5 184.2 242.2 184.2 344.2C184.2 453.7 322.5 458.2 367.7 387.4C374.2 397.6 403.1 424.9 413 434.2L469.8 378.2C469.8 378.2 437.5 352.9 437.5 325.4L437.5 178.3C437.5 153 413 96 325.2 96C237.2 96 190.5 151 190.5 200.3L264 207.1C280.3 157.6 318.2 157.6 318.2 157.6C358.9 157.5 353.7 187.4 353.7 226.7zM353.7 313.5C353.7 393.5 269.5 381.5 269.5 330.7C269.5 283.5 320 274 353.7 272.9L353.7 313.5zM489.7 477C482 487 419.7 544 315.2 544C210.7 544 130.7 472.5 106.2 443C99.4 435.3 107.2 431.7 111.7 434.7C185 479.2 299.5 552.5 484.2 465C491.7 461.3 497.5 467 489.7 477zM529.5 479.2C523 495 513.5 506 508.3 510.2C502.8 514.7 498.8 512.9 501.8 506.4C504.8 499.9 521.1 459.9 514.5 451.4C508 443.1 477.5 447.1 466.5 448.2C455.7 449.2 453.5 450.2 452.5 447.9C450.2 442.2 474.2 432.4 490 430.4C505.7 428.6 531 429.6 536 436.1C539.7 441.2 536 463.2 529.5 479.2z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="currentColor"&gt;&lt;!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--&gt;&lt;path d="M353.7 226.7C305 228.5 184.2 242.2 184.2 344.2C184.2 453.7 322.5 458.2 367.7 387.4C374.2 397.6 403.1 424.9 413 434.2L469.8 378.2C469.8 378.2 437.5 352.9 437.5 325.4L437.5 178.3C437.5 153 413 96 325.2 96C237.2 96 190.5 151 190.5 200.3L264 207.1C280.3 157.6 318.2 157.6 318.2 157.6C358.9 157.5 353.7 187.4 353.7 226.7zM353.7 313.5C353.7 393.5 269.5 381.5 269.5 330.7C269.5 283.5 320 274 353.7 272.9L353.7 313.5zM489.7 477C482 487 419.7 544 315.2 544C210.7 544 130.7 472.5 106.2 443C99.4 435.3 107.2 431.7 111.7 434.7C185 479.2 299.5 552.5 484.2 465C491.7 461.3 497.5 467 489.7 477zM529.5 479.2C523 495 513.5 506 508.3 510.2C502.8 514.7 498.8 512.9 501.8 506.4C504.8 499.9 521.1 459.9 514.5 451.4C508 443.1 477.5 447.1 466.5 448.2C455.7 449.2 453.5 450.2 452.5 447.9C450.2 442.2 474.2 432.4 490 430.4C505.7 428.6 531 429.6 536 436.1C539.7 441.2 536 463.2 529.5 479.2z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="currentColor"&gt;&lt;!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--&gt;&lt;path d="M353.7 226.7C305 228.5 184.2 242.2 184.2 344.2C184.2 453.7 322.5 458.2 367.7 387.4C374.2 397.6 403.1 424.9 413 434.2L469.8 378.2C469.8 378.2 437.5 352.9 437.5 325.4L437.5 178.3C437.5 153 413 96 325.2 96C237.2 96 190.5 151 190.5 200.3L264 207.1C280.3 157.6 318.2 157.6 318.2 157.6C358.9 157.5 353.7 187.4 353.7 226.7zM353.7 313.5C353.7 393.5 269.5 381.5 269.5 330.7C269.5 283.5 320 274 353.7 272.9L353.7 313.5zM489.7 477C482 487 419.7 544 315.2 544C210.7 544 130.7 472.5 106.2 443C99.4 435.3 107.2 431.7 111.7 434.7C185 479.2 299.5 552.5 484.2 465C491.7 461.3 497.5 467 489.7 477zM529.5 479.2C523 495 513.5 506 508.3 510.2C502.8 514.7 498.8 512.9 501.8 506.4C504.8 499.9 521.1 459.9 514.5 451.4C508 443.1 477.5 447.1 466.5 448.2C455.7 449.2 453.5 450.2 452.5 447.9C450.2 442.2 474.2 432.4 490 430.4C505.7 428.6 531 429.6 536 436.1C539.7 441.2 536 463.2 529.5 479.2z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="currentColor"&gt;&lt;!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--&gt;&lt;path d="M353.7 226.7C305 228.5 184.2 242.2 184.2 344.2C184.2 453.7 322.5 458.2 367.7 387.4C374.2 397.6 403.1 424.9 413 434.2L469.8 378.2C469.8 378.2 437.5 352.9 437.5 325.4L437.5 178.3C437.5 153 413 96 325.2 96C237.2 96 190.5 151 190.5 200.3L264 207.1C280.3 157.6 318.2 157.6 318.2 157.6C358.9 157.5 353.7 187.4 353.7 226.7zM353.7 313.5C353.7 393.5 269.5 381.5 269.5 330.7C269.5 283.5 320 274 353.7 272.9L353.7 313.5zM489.7 477C482 487 419.7 544 315.2 544C210.7 544 130.7 472.5 106.2 443C99.4 435.3 107.2 431.7 111.7 434.7C185 479.2 299.5 552.5 484.2 465C491.7 461.3 497.5 467 489.7 477zM529.5 479.2C523 495 513.5 506 508.3 510.2C502.8 514.7 498.8 512.9 501.8 506.4C504.8 499.9 521.1 459.9 514.5 451.4C508 443.1 477.5 447.1 466.5 448.2C455.7 449.2 453.5 450.2 452.5 447.9C450.2 442.2 474.2 432.4 490 430.4C505.7 428.6 531 429.6 536 436.1C539.7 441.2 536 463.2 529.5 479.2z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" fill="currentColor"&gt;&lt;!--!Font Awesome Free v7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--&gt;&lt;path d="M353.7 226.7C305 228.5 184.2 242.2 184.2 344.2C184.2 453.7 322.5 458.2 367.7 387.4C374.2 397.6 403.1 424.9 413 434.2L469.8 378.2C469.8 378.2 437.5 352.9 437.5 325.4L437.5 178.3C437.5 153 413 96 325.2 96C237.2 96 190.5 151 190.5 200.3L264 207.1C280.3 157.6 318.2 157.6 318.2 157.6C358.9 157.5 353.7 187.4 353.7 226.7zM353.7 313.5C353.7 393.5 269.5 381.5 269.5 330.7C269.5 283.5 320 274 353.7 272.9L353.7 313.5zM489.7 477C482 487 419.7 544 315.2 544C210.7 544 130.7 472.5 106.2 443C99.4 435.3 107.2 431.7 111.7 434.7C185 479.2 299.5 552.5 484.2 465C491.7 461.3 497.5 467 489.7 477zM529.5 479.2C523 495 513.5 506 508.3 510.2C502.8 514.7 498.8 512.9 501.8 506.4C504.8 499.9 521.1 459.9 514.5 451.4C508 443.1 477.5 447.1 466.5 448.2C455.7 449.2 453.5 450.2 452.5 447.9C450.2 442.2 474.2 432.4 490 430.4C505.7 428.6 531 429.6 536 436.1C539.7 441.2 536 463.2 529.5 479.2z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="blogs--tutorials"&gt;Blogs / Tutorials&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="software-git-clients"&gt;Software (git Clients)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Die meisten heutigen IDEs und Editoren verfügen über direkte Integration mit einer Versionsverwaltung, vor allem auch mit git.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;Android Studio&lt;/li&gt;
&lt;li&gt;JetBrains InteliJ, Rider, PyCharm und weitere&lt;/li&gt;
&lt;li&gt;Visuals Studio&lt;/li&gt;
&lt;li&gt;XCode&lt;/li&gt;
&lt;li&gt;und viele weitere&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="git-hoster"&gt;Git Hoster&lt;/h2&gt;
&lt;p&gt;Alle Hoster bieten ein kostenkoses Konto an. Mit diesem ist es meistens möglich mit bis zu 5 Mitstreitern kostenlos zusammenzuarbeiten und unbegrenzte Anzahl an privaten Repositories zu haben. Viele bieten auch ein kostenloses Zeitkontingent für die integrierte CI/CD Pipeline.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;g fill="#181616"&gt;&lt;path fill-rule="evenodd" d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388c0 26.682 17.303 49.317 41.297 57.303c3.017.56 4.125-1.31 4.125-2.905c0-1.44-.056-6.197-.082-11.243c-16.8 3.653-20.345-7.125-20.345-7.125c-2.747-6.98-6.705-8.836-6.705-8.836c-5.48-3.748.413-3.67.413-3.67c6.063.425 9.257 6.223 9.257 6.223c5.386 9.23 14.127 6.562 17.573 5.02c.542-3.903 2.107-6.568 3.834-8.076c-13.413-1.525-27.514-6.704-27.514-29.843c0-6.593 2.36-11.98 6.223-16.21c-.628-1.52-2.695-7.662.584-15.98c0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033c11.526-7.813 16.59-6.19 16.59-6.19c3.287 8.317 1.22 14.46.593 15.98c3.872 4.23 6.215 9.617 6.215 16.21c0 23.194-14.127 28.3-27.574 29.796c2.167 1.874 4.097 5.55 4.097 11.183c0 8.08-.07 14.583-.07 16.572c0 1.607 1.088 3.49 4.148 2.897c23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z" clip-rule="evenodd"/&gt;&lt;path d="M26.484 91.806c-.133.3-.605.39-1.035.185c-.44-.196-.685-.605-.543-.906c.13-.31.603-.395 1.04-.188c.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28c-.396-.42-.47-.983-.177-1.254c.298-.266.844-.14 1.24.28c.394.426.472.984.17 1.255zm2.382 3.477c-.37.258-.976.017-1.35-.52c-.37-.538-.37-1.183.01-1.44c.373-.258.97-.025 1.35.507c.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23c-.527-.487-.674-1.18-.343-1.544c.336-.366 1.045-.264 1.564.23c.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486c-.683-.207-1.13-.76-.99-1.238c.14-.477.823-.7 1.512-.485c.683.206 1.13.756.988 1.237m4.943.361c.017.498-.563.91-1.28.92c-.723.017-1.308-.387-1.315-.877c0-.503.568-.91 1.29-.924c.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117c-.7.13-1.35-.172-1.44-.653c-.086-.498.422-.997 1.122-1.126c.714-.123 1.354.17 1.444.663zm0 0"/&gt;&lt;/g&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;defs&gt;&lt;linearGradient id="SVGlTkM2b2Q" x1="28.593" x2="16.672" y1="14.226" y2="23.532" gradientTransform="scale(4)" gradientUnits="userSpaceOnUse"&gt;&lt;stop offset=".176" stop-color="#0052cc"/&gt;&lt;stop offset="1" stop-color="#2684ff"/&gt;&lt;/linearGradient&gt;&lt;/defs&gt;&lt;path fill="#2684ff" d="M19.082 20c-1.918 0-3.355 1.758-3.039 3.516l12.95 79.289c.32 2.078 2.077 3.515 4.155 3.515h62.66c1.442 0 2.72-1.12 3.04-2.558l13.109-80.086c.316-1.918-1.121-3.516-3.039-3.516zM74.07 77.227H54.09l-5.278-28.293h30.215zm0 0"/&gt;&lt;path fill="url(#SVGlTkM2b2Q)" d="M107.64 48.934H78.868L74.07 77.227H54.09l-23.5 27.972s1.12.961 2.719.961h62.66c1.441 0 2.719-1.12 3.039-2.558zm0 0"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;path fill="#e24329" d="m124.755 51.382l-.177-.452L107.47 6.282a4.46 4.46 0 0 0-1.761-2.121a4.58 4.58 0 0 0-5.236.281a4.6 4.6 0 0 0-1.518 2.304L87.404 42.088H40.629L29.077 6.746a4.5 4.5 0 0 0-1.518-2.31a4.58 4.58 0 0 0-5.236-.281a4.5 4.5 0 0 0-1.761 2.121L3.422 50.904l-.17.452c-5.059 13.219-.763 28.192 10.537 36.716l.059.046l.157.111l26.061 19.516l12.893 9.758l7.854 5.93a5.28 5.28 0 0 0 6.388 0l7.854-5.93l12.893-9.758l26.218-19.634l.065-.052c11.273-8.526 15.562-23.472 10.524-36.677"/&gt;&lt;path fill="#fc6d26" d="m124.755 51.382l-.177-.452a57.8 57.8 0 0 0-23.005 10.341L64 89.682c12.795 9.68 23.934 18.09 23.934 18.09l26.218-19.634l.065-.052c11.291-8.527 15.586-23.488 10.538-36.704"/&gt;&lt;path fill="#fca326" d="m40.066 107.771l12.893 9.758l7.854 5.93a5.28 5.28 0 0 0 6.388 0l7.854-5.93l12.893-9.758s-11.152-8.436-23.947-18.09a18379 18379 0 0 0-23.935 18.09"/&gt;&lt;path fill="#fc6d26" d="M26.42 61.271A57.7 57.7 0 0 0 3.422 50.904l-.17.452c-5.059 13.219-.763 28.192 10.537 36.716l.059.046l.157.111l26.061 19.516L64 89.655z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="inline-block pr-1"&gt;
&lt;svg style="height: 1em; transform: translateY(0.1em);" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"&gt;&lt;defs&gt;&lt;linearGradient id="SVG6uMEBcPj" x1="9" x2="9" y1="16.97" y2="1.03" gradientTransform="scale(7.11111)" gradientUnits="userSpaceOnUse"&gt;&lt;stop offset="0" stop-color="#0078d4"/&gt;&lt;stop offset=".16" stop-color="#1380da"/&gt;&lt;stop offset=".53" stop-color="#3c91e5"/&gt;&lt;stop offset=".82" stop-color="#559cec"/&gt;&lt;stop offset="1" stop-color="#5ea0ef"/&gt;&lt;/linearGradient&gt;&lt;/defs&gt;&lt;path fill="url(#SVG6uMEBcPj)" d="M120.89 28.445v69.262l-28.445 23.324l-44.09-16.07v15.93L23.395 88.25l72.746 5.688V31.574ZM96.64 31.93L55.82 7.11v16.285L18.348 34.418L7.109 48.852v32.785l16.075 7.11V46.718Zm0 0"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Container / Docker für Einsteiger*innen am eigenen Laptop</title><link>https://kurse.richter.consulting/events/docker-x486660/</link><pubDate>Tue, 02 Jun 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/docker-x486660/</guid><description>&lt;p&gt;Die eigene Software ist oft von externen Services abhängig. Diese können auf dem Entwicklungsrechner installiert werden. Noch einfacher, sicherer und schneller geht es aber mit den Containern. Lernen Sie in diesem Kurs die Grundlagen von Docker, Container, Images, Orchestrierung, Docker Compose, die Sie für Ihren eigenen
Entwickleralltag benötigen.&lt;/p&gt;
&lt;h2 id="voraussetzung"&gt;Voraussetzung:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;sicherer Umgang mit einem PC sowie&lt;/li&gt;
&lt;li&gt;grundlegende Programmierkenntnisse.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Bitte bringen Sie Ihren Laptop oder MacGerät inkl. Ladegerät mit.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="nächster-termin-an-der-mvhs"&gt;Nächster Termin an der MVHS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 12.12.2026 - 13.12.2026
&lt;ol&gt;
&lt;li&gt;Sa. 12.12.2026, 10:00 – 15:00 Uhr&lt;/li&gt;
&lt;li&gt;So. 13.12.2026, 10:00 – 15:00 Uhr&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Git - Versionsverwaltung für Dokumente, Dokumentationen, Code und mehr</title><link>https://kurse.richter.consulting/events/git-x486650/</link><pubDate>Tue, 02 Jun 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/git-x486650/</guid><description>&lt;p&gt;Arbeiten Sie in einer Gruppe an einem Dokument oder programmieren Sie gerne? Wollen Sie wissen, was Sie oder Andere zuletzt am Dokument geändert haben?&lt;/p&gt;
&lt;h2 id="erfahren-sie-mehr-dazu"&gt;Erfahren Sie mehr dazu&lt;/h2&gt;
&lt;p&gt;Lernen Sie, wie eine Version (von einem oder mehreren Dokumenten) mit Git auf dem Rechner gesichert, verglichen, mit anderen geteilt, zusammengeführt und wiederhergestellt werden kann. Erstellen Sie mehrere Bearbeitungszweige, um an mehreren Dokumentversionen parallel arbeiten zu können.&lt;/p&gt;
&lt;p&gt;Kursinhalt: Grundlagen Versionierung; Geschichte; aktuelle Systeme; Strategien; lokaler Einsatz von Git; Git mit Server-Einsatz; Arbeiten an mehreren Zweigen.&lt;/p&gt;
&lt;h2 id="nächster-termin-an-der-mvhs"&gt;Nächster Termin an der MVHS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 18.11.2026 - 25.11.2026
&lt;ol&gt;
&lt;li&gt;Mi. 18.11.2026, 18:00 – 21:00 Uhr&lt;/li&gt;
&lt;li&gt;Mi. 25.11.2026, 18:00 – 21:00 Uhr&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Jetzt lerne ich mein Android-Smartphone kennen</title><link>https://kurse.richter.consulting/events/android-x483610/</link><pubDate>Tue, 02 Jun 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/android-x483610/</guid><description>&lt;p&gt;Entdecken Sie die Welt von Android, dem führenden Betriebssystem für Smartphones und Tablets. In diesem Kurs werden Ihnen neben grundlegenden Funktionen auch nützliche Tipps zur optimalen Nutzung Ihres Gerätes aufgezeigt.&lt;/p&gt;
&lt;h2 id="kursinhalte"&gt;Kursinhalte:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Vorstellung einzelner Android-Versionen und einfache
Anpassungen&lt;/li&gt;
&lt;li&gt;Einrichten von WLAN-Zugang&lt;/li&gt;
&lt;li&gt;Telefonieren und fotografieren&lt;/li&gt;
&lt;li&gt;Abspielen von Musik und Videos&lt;/li&gt;
&lt;li&gt;Nutzung von Gmail oder E-Mail&lt;/li&gt;
&lt;li&gt;Surfen im Internet&lt;/li&gt;
&lt;li&gt;Sicherheitsaspekte und hilfreiche Tipps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Erfahrungen im Umgang mit einem Touchscreen werden vorausgesetzt. Die Grundfunktionen werden an einem Android-Gerät exemplarisch demonstriert.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Bitte bringen Sie ein Android-Smartphone inkl. Ladegerät mit.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="termine"&gt;Termine&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 28.11.2026 - 29.11.2026
&lt;ol&gt;
&lt;li&gt;Sa. 28.11.2026, 10:00 - 13:00&lt;/li&gt;
&lt;li&gt;So. 29.11.2026, 10:00 - 13:00&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MacOS: das Apple-Betriebssystem besser kennenlernen</title><link>https://kurse.richter.consulting/events/macos-x483430/</link><pubDate>Tue, 02 Jun 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/macos-x483430/</guid><description>&lt;p&gt;Sie haben bereits Erfahrungen im Umgang mit Ihrem MacBook und möchten jetzt weitere Anwendungs- und Wartungsprogramme sowie Konfigurationsmöglichkeiten von macOS kennenlernen?&lt;/p&gt;
&lt;h2 id="erfahren-sie-mehr-zu"&gt;Erfahren Sie mehr zu:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Hardwarekomponenten und -erweiterungen&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;Systemeinstellungen, -optimierung und -sicherung&lt;/li&gt;
&lt;li&gt;Tipps und Tricks im Umgang mit dem Finder&lt;/li&gt;
&lt;li&gt;Einrichten von Internet und Netzwerk&lt;/li&gt;
&lt;li&gt;Nutzen der Cloud-Dienste&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Bitte bringen Sie ein MacBook inkl. Ladegerät mit.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="nächster-termin-an-der-mvhs"&gt;Nächster Termin an der MVHS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 27.02.2027 - 28.02.2027
&lt;ol&gt;
&lt;li&gt;Sa. 27.02.2027, 09:15 – 16:00 Uhr&lt;/li&gt;
&lt;li&gt;So. 28.02.2027, 09:15 – 16:00 Uhr&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Container / Docker für Einsteiger*innen am eigenen Laptop</title><link>https://kurse.richter.consulting/events/docker-w486660/</link><pubDate>Sun, 01 Feb 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/docker-w486660/</guid><description>&lt;p&gt;Die eigene Software ist oft von externen Services abhängig. Diese können auf dem Entwicklungsrechner installiert werden. Noch einfacher, sicherer und schneller geht es aber mit den Containern. Lernen Sie in diesem Kurs die Grundlagen von Docker, Container, Images, Orchestrierung, Docker Compose, die Sie für Ihren eigenen
Entwickleralltag benötigen.&lt;/p&gt;
&lt;h2 id="voraussetzung"&gt;Voraussetzung:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;sicherer Umgang mit einem PC sowie&lt;/li&gt;
&lt;li&gt;grundlegende Programmierkenntnisse.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Bitte bringen Sie Ihren Laptop oder MacGerät inkl. Ladegerät mit.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="nächster-termin-an-der-mvhs"&gt;Nächster Termin an der MVHS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 13.06.2026 - 14.06.2026
&lt;ol&gt;
&lt;li&gt;Sa. 13.06.2026, 10:00 – 15:00 Uhr&lt;/li&gt;
&lt;li&gt;So. 14.06.2026, 10:00 – 15:00 Uhr&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Der geht doch noch! Ältere Computer und Laptops sicher weiterverwenden</title><link>https://kurse.richter.consulting/events/alt-261-32004/</link><pubDate>Sun, 01 Feb 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/alt-261-32004/</guid><description>&lt;p&gt;Die Sicherheitsupdates von Windows 10 werden im Oktober eingestellt – und nun? In diesem Überblicksworkshop erfahren Sie, wie Sie Ihren älteren PC sicher und sinnvoll weiter nutzen können: mit Updates, Optimierungen oder passenden Alternativen. So bleibt Ihr Gerät ein zuverlässiger Begleiter – auch über 2025 hinaus. Warum das Support-Ende ein Problem und Risiko darstellen kann, erklärt dieser Artikel des WDR:
&lt;/p&gt;
&lt;p&gt;Am Ende des Kurses wissen Sie, welche Optionen Ihnen zur Verfügung stehen, um Ihr Gerät weiterhin sicher und effizient zu nutzen.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-emerald-100 dark:bg-emerald-900 border-emerald-500"
data-callout="tip"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-emerald-600 dark:text-emerald-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 18v-5.25m0 0a6 6 0 0 0 1.5-.189m-1.5.189a6 6 0 0 1-1.5-.189m3.75 7.478a12.1 12.1 0 0 1-4.5 0m3.75 2.383a14.4 14.4 0 0 1-3 0M14.25 18v-.192c0-.983.658-1.823 1.508-2.316a7.5 7.5 0 1 0-7.517 0c.85.493 1.509 1.333 1.509 2.316V18"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Tipp&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Wer direkt den nächsten Schritt machen möchte, kann im passenden Folgekurs
(Sa. 27.06.2026, 10–15 Uhr) die Installation und erste Schritte mit einem neuen Betriebssystem erlernen!&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Jetzt lerne ich mein Android-Smartphone kennen</title><link>https://kurse.richter.consulting/events/android-w483610/</link><pubDate>Sun, 01 Feb 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/android-w483610/</guid><description>&lt;p&gt;Entdecken Sie die Welt von Android, dem führenden Betriebssystem für Smartphones und Tablets. In diesem Kurs werden Ihnen neben grundlegenden Funktionen auch nützliche Tipps zur optimalen Nutzung Ihres Gerätes aufgezeigt.&lt;/p&gt;
&lt;h2 id="kursinhalte"&gt;Kursinhalte:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Vorstellung einzelner Android-Versionen und einfache
Anpassungen&lt;/li&gt;
&lt;li&gt;Einrichten von WLAN-Zugang&lt;/li&gt;
&lt;li&gt;Telefonieren und fotografieren&lt;/li&gt;
&lt;li&gt;Abspielen von Musik und Videos&lt;/li&gt;
&lt;li&gt;Nutzung von Gmail oder E-Mail&lt;/li&gt;
&lt;li&gt;Surfen im Internet&lt;/li&gt;
&lt;li&gt;Sicherheitsaspekte und hilfreiche Tipps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Erfahrungen im Umgang mit einem Touchscreen werden vorausgesetzt. Die Grundfunktionen werden an einem Android-Gerät exemplarisch demonstriert.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Bitte bringen Sie ein Android-Smartphone inkl. Ladegerät mit.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="termine"&gt;Termine&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 20.06.2026 - 21.06.2026
&lt;ol&gt;
&lt;li&gt;Sa. 20.06.2026, 10:00 - 13:00&lt;/li&gt;
&lt;li&gt;So. 21.06.2026, 10:00 - 13:00&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Linux leicht gemacht: Der einfache Einstieg für Anfänger (mit Installation)</title><link>https://kurse.richter.consulting/events/linux-261-32005/</link><pubDate>Sun, 01 Feb 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/linux-261-32005/</guid><description>&lt;p&gt;Sie verwenden einen älteren Computer und möchten ihn sicher weiter nutzen? Oder suchen Sie eine Alternative zu Windows, die zuverlässig und kostenlos ist? Linux ist eine bewährte Alternative: Es ist sicher, läuft stabil und eignet sich besonders für ältere Geräte. Zudem machen Sie sich unabhängig von kostenpflichtigen Updates oder neuen Windows-Versionen. Hintergrund ist, dass Microsoft die kostenlosen Sicherheitsupdates für Windows 10 am 14. Oktober 2025 beendet.&lt;/p&gt;
&lt;p&gt;Viele Programme und Abläufe in Linux ähneln Windows, sodass der Umstieg leichter ist als gedacht. In diesem Workshop lernen Sie Schritt für Schritt, wie Sie Linux auf Ihrem Computer installieren und erste wichtige Einstellungen vornehmen. Wir zeigen Ihnen, welche Linux-Variante sich für Ihre Bedürfnisse eignet, wie Sie Programme installieren und welche grundlegenden Funktionen Ihnen den Einstieg erleichtern. Alles in verständlicher Sprache und mit praktischen Übungen. Nach Kursende nehmen Sie einen voll einsatzbereiten Linux-Rechner mit nach Hause – bereit für einen sicheren und effizienten Einsatz!&lt;/p&gt;
&lt;p&gt;Wichtig: Bitte bringen Sie ein eigenes Endgerät sowie einen USB-Stick (mindestens 8 GB, idealerweise USB 3.0) mit. Damit können Sie das neue System direkt ausprobieren und individuell einrichten.&lt;/p&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Dieser Kurs eignet sich besonders gut als praktische Ergänzung zum Überblicks-Workshop
(261-32004), in dem Sie erfahren, wann und warum ein Umstieg sinnvoll sein kann.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>MacOS: das Apple-Betriebssystem besser kennenlernen</title><link>https://kurse.richter.consulting/events/macos-w483430/</link><pubDate>Sun, 01 Feb 2026 07:00:00 +0100</pubDate><guid>https://kurse.richter.consulting/events/macos-w483430/</guid><description>&lt;p&gt;Sie haben bereits Erfahrungen im Umgang mit Ihrem MacBook und möchten jetzt weitere Anwendungs- und Wartungsprogramme sowie Konfigurationsmöglichkeiten von macOS kennenlernen?&lt;/p&gt;
&lt;h2 id="erfahren-sie-mehr-zu"&gt;Erfahren Sie mehr zu:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Hardwarekomponenten und -erweiterungen&lt;/li&gt;
&lt;li&gt;Systemeinstellungen, -optimierung und -sicherung&lt;/li&gt;
&lt;li&gt;Tipps und Tricks im Umgang mit dem Finder&lt;/li&gt;
&lt;li&gt;Einrichten von Internet und Netzwerk&lt;/li&gt;
&lt;li&gt;Nutzen der Cloud-Dienste&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 bg-blue-100 dark:bg-blue-900 border-blue-500"
data-callout="note"
data-callout-metadata=""&gt;
&lt;span class="callout-icon pr-3 pt-1 text-blue-600 dark:text-blue-300"&gt;
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"&gt;&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8l.8-2.685a4.5 4.5 0 0 1 1.13-1.897zm0 0L19.5 7.125"/&gt;&lt;/svg&gt;
&lt;/span&gt;
&lt;div class="callout-content dark:text-neutral-300"&gt;
&lt;div class="callout-title font-semibold mb-1"&gt;Hinweis&lt;/div&gt;
&lt;div class="callout-body"&gt;&lt;p&gt;Bitte bringen Sie ein MacBook inkl. Ladegerät mit.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="nächster-termin-an-der-mvhs"&gt;Nächster Termin an der MVHS&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2x, 25.07.2026 - 26.07.2026
&lt;ol&gt;
&lt;li&gt;Sa. 25.07.2026, 09:15 – 16:00 Uhr&lt;/li&gt;
&lt;li&gt;So. 26.07.2026, 09:15 – 16:00 Uhr&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>