diff --git a/generatedDocs/github-markdown.css b/generatedDocs/github-markdown.css new file mode 100644 index 00000000..257b9211 --- /dev/null +++ b/generatedDocs/github-markdown.css @@ -0,0 +1,1254 @@ +.markdown-body { + --base-size-4: 0.25rem; + --base-size-8: 0.5rem; + --base-size-16: 1rem; + --base-size-24: 1.5rem; + --base-size-40: 2.5rem; + --base-text-weight-normal: 400; + --base-text-weight-medium: 500; + --base-text-weight-semibold: 600; + --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; + --fgColor-accent: Highlight; +} +@media (prefers-color-scheme: dark) { + .markdown-body, [data-theme="dark"] { + /* dark */ + color-scheme: dark; + --focus-outlineColor: #1f6feb; + --fgColor-default: #f0f6fc; + --fgColor-muted: #9198a1; + --fgColor-accent: #4493f8; + --fgColor-success: #3fb950; + --fgColor-attention: #d29922; + --fgColor-danger: #f85149; + --fgColor-done: #ab7df8; + --bgColor-default: #0d1117; + --bgColor-muted: #151b23; + --bgColor-neutral-muted: #656c7633; + --bgColor-attention-muted: #bb800926; + --borderColor-default: #3d444d; + --borderColor-muted: #3d444db3; + --borderColor-neutral-muted: #3d444db3; + --borderColor-accent-emphasis: #1f6feb; + --borderColor-success-emphasis: #238636; + --borderColor-attention-emphasis: #9e6a03; + --borderColor-danger-emphasis: #da3633; + --borderColor-done-emphasis: #8957e5; + --color-prettylights-syntax-comment: #9198a1; + --color-prettylights-syntax-constant: #79c0ff; + --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; + --color-prettylights-syntax-entity: #d2a8ff; + --color-prettylights-syntax-storage-modifier-import: #f0f6fc; + --color-prettylights-syntax-entity-tag: #7ee787; + --color-prettylights-syntax-keyword: #ff7b72; + --color-prettylights-syntax-string: #a5d6ff; + --color-prettylights-syntax-variable: #ffa657; + --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; + --color-prettylights-syntax-brackethighlighter-angle: #9198a1; + --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; + --color-prettylights-syntax-invalid-illegal-bg: #8e1519; + --color-prettylights-syntax-carriage-return-text: #f0f6fc; + --color-prettylights-syntax-carriage-return-bg: #b62324; + --color-prettylights-syntax-string-regexp: #7ee787; + --color-prettylights-syntax-markup-list: #f2cc60; + --color-prettylights-syntax-markup-heading: #1f6feb; + --color-prettylights-syntax-markup-italic: #f0f6fc; + --color-prettylights-syntax-markup-bold: #f0f6fc; + --color-prettylights-syntax-markup-deleted-text: #ffdcd7; + --color-prettylights-syntax-markup-deleted-bg: #67060c; + --color-prettylights-syntax-markup-inserted-text: #aff5b4; + --color-prettylights-syntax-markup-inserted-bg: #033a16; + --color-prettylights-syntax-markup-changed-text: #ffdfb6; + --color-prettylights-syntax-markup-changed-bg: #5a1e02; + --color-prettylights-syntax-markup-ignored-text: #f0f6fc; + --color-prettylights-syntax-markup-ignored-bg: #1158c7; + --color-prettylights-syntax-meta-diff-range: #d2a8ff; + --color-prettylights-syntax-sublimelinter-gutter-mark: #3d444d; + } +} +@media (prefers-color-scheme: light) { + .markdown-body, [data-theme="light"] { + /* light */ + color-scheme: light; + --focus-outlineColor: #0969da; + --fgColor-default: #1f2328; + --fgColor-muted: #59636e; + --fgColor-accent: #0969da; + --fgColor-success: #1a7f37; + --fgColor-attention: #9a6700; + --fgColor-danger: #d1242f; + --fgColor-done: #8250df; + --bgColor-default: #ffffff; + --bgColor-muted: #f6f8fa; + --bgColor-neutral-muted: #818b981f; + --bgColor-attention-muted: #fff8c5; + --borderColor-default: #d1d9e0; + --borderColor-muted: #d1d9e0b3; + --borderColor-neutral-muted: #d1d9e0b3; + --borderColor-accent-emphasis: #0969da; + --borderColor-success-emphasis: #1a7f37; + --borderColor-attention-emphasis: #9a6700; + --borderColor-danger-emphasis: #cf222e; + --borderColor-done-emphasis: #8250df; + --color-prettylights-syntax-comment: #59636e; + --color-prettylights-syntax-constant: #0550ae; + --color-prettylights-syntax-constant-other-reference-link: #0a3069; + --color-prettylights-syntax-entity: #6639ba; + --color-prettylights-syntax-storage-modifier-import: #1f2328; + --color-prettylights-syntax-entity-tag: #0550ae; + --color-prettylights-syntax-keyword: #cf222e; + --color-prettylights-syntax-string: #0a3069; + --color-prettylights-syntax-variable: #953800; + --color-prettylights-syntax-brackethighlighter-unmatched: #82071e; + --color-prettylights-syntax-brackethighlighter-angle: #59636e; + --color-prettylights-syntax-invalid-illegal-text: #f6f8fa; + --color-prettylights-syntax-invalid-illegal-bg: #82071e; + --color-prettylights-syntax-carriage-return-text: #f6f8fa; + --color-prettylights-syntax-carriage-return-bg: #cf222e; + --color-prettylights-syntax-string-regexp: #116329; + --color-prettylights-syntax-markup-list: #3b2300; + --color-prettylights-syntax-markup-heading: #0550ae; + --color-prettylights-syntax-markup-italic: #1f2328; + --color-prettylights-syntax-markup-bold: #1f2328; + --color-prettylights-syntax-markup-deleted-text: #82071e; + --color-prettylights-syntax-markup-deleted-bg: #ffebe9; + --color-prettylights-syntax-markup-inserted-text: #116329; + --color-prettylights-syntax-markup-inserted-bg: #dafbe1; + --color-prettylights-syntax-markup-changed-text: #953800; + --color-prettylights-syntax-markup-changed-bg: #ffd8b5; + --color-prettylights-syntax-markup-ignored-text: #d1d9e0; + --color-prettylights-syntax-markup-ignored-bg: #0550ae; + --color-prettylights-syntax-meta-diff-range: #8250df; + --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98; + } +} + +.markdown-body { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + color: var(--fgColor-default); + background-color: var(--bgColor-default); + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"; + font-size: 16px; + word-wrap: break-word; + margin: 0; + min-height: 100vh; + line-height: 1.5; + scroll-behavior: smooth; +} + +.markdown-body .octicon { + display: inline-block; + fill: currentColor; + vertical-align: text-bottom; +} + +.markdown-body h1:hover .anchor .octicon-link:before, +.markdown-body h2:hover .anchor .octicon-link:before, +.markdown-body h3:hover .anchor .octicon-link:before, +.markdown-body h4:hover .anchor .octicon-link:before, +.markdown-body h5:hover .anchor .octicon-link:before, +.markdown-body h6:hover .anchor .octicon-link:before { + width: 16px; + height: 16px; + content: ' '; + display: inline-block; + background-color: currentColor; + -webkit-mask-image: url("data:image/svg+xml,"); + mask-image: url("data:image/svg+xml,"); +} + +.markdown-body details, +.markdown-body figcaption, +.markdown-body figure { + display: block; +} + +.markdown-body summary { + display: list-item; +} + +.markdown-body [hidden] { + display: none !important; +} + +.markdown-body a { + background-color: transparent; + color: var(--fgColor-accent); + text-decoration: none; +} + +.markdown-body abbr[title] { + border-bottom: none; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +.markdown-body b, +.markdown-body strong { + font-weight: var(--base-text-weight-semibold, 600); +} + +.markdown-body dfn { + font-style: italic; +} + +.markdown-body h1 { + margin: .67em 0; + font-weight: var(--base-text-weight-semibold, 600); + padding-bottom: .3em; + font-size: 2em; + border-bottom: 1px solid var(--borderColor-muted); +} + +.markdown-body mark { + background-color: var(--bgColor-attention-muted); + color: var(--fgColor-default); +} + +.markdown-body small { + font-size: 90%; +} + +.markdown-body sub, +.markdown-body sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +.markdown-body sub { + bottom: -0.25em; +} + +.markdown-body sup { + top: -0.5em; +} + +.markdown-body img { + border-style: none; + max-width: 100%; + box-sizing: content-box; +} + +.markdown-body code, +.markdown-body kbd, +.markdown-body pre, +.markdown-body samp { + font-family: monospace; + font-size: 1em; +} + +.markdown-body figure { + margin: 1em var(--base-size-40); +} + +.markdown-body hr { + box-sizing: content-box; + overflow: hidden; + background: transparent; + border-bottom: 1px solid var(--borderColor-muted); + height: .25em; + padding: 0; + margin: var(--base-size-24) 0; + background-color: var(--borderColor-default); + border: 0; +} + +.markdown-body input { + margin: 0; + overflow: visible; + font-family: inherit; + font-size: inherit; + line-height: inherit; + font: inherit; +} + +.markdown-body [type=button], +.markdown-body [type=reset], +.markdown-body [type=submit] { + -webkit-appearance: button; + appearance: button; +} + +.markdown-body [type=checkbox], +.markdown-body [type=radio] { + box-sizing: border-box; + padding: 0; +} + +.markdown-body [type=number]::-webkit-inner-spin-button, +.markdown-body [type=number]::-webkit-outer-spin-button { + height: auto; +} + +.markdown-body [type=search]::-webkit-search-cancel-button, +.markdown-body [type=search]::-webkit-search-decoration { + -webkit-appearance: none; + appearance: none; +} + +.markdown-body ::-webkit-input-placeholder { + color: inherit; + opacity: .54; +} + +.markdown-body ::-webkit-file-upload-button { + -webkit-appearance: button; + appearance: button; + font: inherit; +} + +.markdown-body a:hover { + text-decoration: underline; +} + +.markdown-body ::placeholder { + color: var(--fgColor-muted); + opacity: 1; +} + +.markdown-body hr::before { + display: table; + content: ""; +} + +.markdown-body hr::after { + display: table; + clear: both; + content: ""; +} + +.markdown-body table { + border-spacing: 0; + border-collapse: collapse; + display: block; + width: max-content; + max-width: 100%; + overflow: auto; + font-variant: tabular-nums; +} + +.markdown-body td, +.markdown-body th { + padding: 0; +} + +.markdown-body details summary { + cursor: pointer; +} + +.markdown-body a:focus, +.markdown-body [role=button]:focus, +.markdown-body input[type=radio]:focus, +.markdown-body input[type=checkbox]:focus { + outline: 2px solid var(--focus-outlineColor); + outline-offset: -2px; + box-shadow: none; +} + +.markdown-body a:focus:not(:focus-visible), +.markdown-body [role=button]:focus:not(:focus-visible), +.markdown-body input[type=radio]:focus:not(:focus-visible), +.markdown-body input[type=checkbox]:focus:not(:focus-visible) { + outline: solid 1px transparent; +} + +.markdown-body a:focus-visible, +.markdown-body [role=button]:focus-visible, +.markdown-body input[type=radio]:focus-visible, +.markdown-body input[type=checkbox]:focus-visible { + outline: 2px solid var(--focus-outlineColor); + outline-offset: -2px; + box-shadow: none; +} + +.markdown-body a:not([class]):focus, +.markdown-body a:not([class]):focus-visible, +.markdown-body input[type=radio]:focus, +.markdown-body input[type=radio]:focus-visible, +.markdown-body input[type=checkbox]:focus, +.markdown-body input[type=checkbox]:focus-visible { + outline-offset: 0; +} + +.markdown-body kbd { + display: inline-block; + padding: var(--base-size-4); + font: 11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace); + line-height: 10px; + color: var(--fgColor-default); + vertical-align: middle; + background-color: var(--bgColor-muted); + border: solid 1px var(--borderColor-neutral-muted); + border-bottom-color: var(--borderColor-neutral-muted); + border-radius: 6px; + box-shadow: inset 0 -1px 0 var(--borderColor-neutral-muted); +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + margin-top: var(--base-size-24); + margin-bottom: var(--base-size-16); + font-weight: var(--base-text-weight-semibold, 600); + line-height: 1.25; +} + +.markdown-body h2 { + font-weight: var(--base-text-weight-semibold, 600); + padding-bottom: .3em; + font-size: 1.5em; + border-bottom: 1px solid var(--borderColor-muted); +} + +.markdown-body h3 { + font-weight: var(--base-text-weight-semibold, 600); + font-size: 1.25em; +} + +.markdown-body h4 { + font-weight: var(--base-text-weight-semibold, 600); + font-size: 1em; +} + +.markdown-body h5 { + font-weight: var(--base-text-weight-semibold, 600); + font-size: .875em; +} + +.markdown-body h6 { + font-weight: var(--base-text-weight-semibold, 600); + font-size: .85em; + color: var(--fgColor-muted); +} + +.markdown-body p { + margin-top: 0; + margin-bottom: 10px; +} + +.markdown-body blockquote { + margin: 0; + padding: 0 1em; + color: var(--fgColor-muted); + border-left: .25em solid var(--borderColor-default); +} + +.markdown-body ul, +.markdown-body ol { + margin-top: 0; + margin-bottom: 0; + padding-left: 2em; +} + +.markdown-body ol ol, +.markdown-body ul ol { + list-style-type: lower-roman; +} + +.markdown-body ul ul ol, +.markdown-body ul ol ol, +.markdown-body ol ul ol, +.markdown-body ol ol ol { + list-style-type: lower-alpha; +} + +.markdown-body dd { + margin-left: 0; +} + +.markdown-body tt, +.markdown-body code, +.markdown-body samp { + font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace); + font-size: 12px; +} + +.markdown-body pre { + margin-top: 0; + margin-bottom: 0; + font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace); + font-size: 12px; + word-wrap: normal; +} + +.markdown-body .octicon { + display: inline-block; + overflow: visible !important; + vertical-align: text-bottom; + fill: currentColor; +} + +.markdown-body input::-webkit-outer-spin-button, +.markdown-body input::-webkit-inner-spin-button { + margin: 0; + appearance: none; +} + +.markdown-body .mr-2 { + margin-right: var(--base-size-8, 8px) !important; +} + +.markdown-body::before { + display: table; + content: ""; +} + +.markdown-body::after { + display: table; + clear: both; + content: ""; +} + +.markdown-body>*:first-child { + margin-top: 0 !important; +} + +.markdown-body>*:last-child { + margin-bottom: 0 !important; +} + +.markdown-body a:not([href]) { + color: inherit; + text-decoration: none; +} + +.markdown-body .absent { + color: var(--fgColor-danger); +} + +.markdown-body .anchor { + float: left; + padding-right: var(--base-size-4); + margin-left: -20px; + line-height: 1; +} + +.markdown-body .anchor:focus { + outline: none; +} + +.markdown-body p, +.markdown-body blockquote, +.markdown-body ul, +.markdown-body ol, +.markdown-body dl, +.markdown-body table, +.markdown-body pre, +.markdown-body details { + margin-top: 0; + margin-bottom: var(--base-size-16); +} + +.markdown-body blockquote>:first-child { + margin-top: 0; +} + +.markdown-body blockquote>:last-child { + margin-bottom: 0; +} + +.markdown-body h1 .octicon-link, +.markdown-body h2 .octicon-link, +.markdown-body h3 .octicon-link, +.markdown-body h4 .octicon-link, +.markdown-body h5 .octicon-link, +.markdown-body h6 .octicon-link { + color: var(--fgColor-default); + vertical-align: middle; + visibility: hidden; +} + +.markdown-body h1:hover .anchor, +.markdown-body h2:hover .anchor, +.markdown-body h3:hover .anchor, +.markdown-body h4:hover .anchor, +.markdown-body h5:hover .anchor, +.markdown-body h6:hover .anchor { + text-decoration: none; +} + +.markdown-body h1:hover .anchor .octicon-link, +.markdown-body h2:hover .anchor .octicon-link, +.markdown-body h3:hover .anchor .octicon-link, +.markdown-body h4:hover .anchor .octicon-link, +.markdown-body h5:hover .anchor .octicon-link, +.markdown-body h6:hover .anchor .octicon-link { + visibility: visible; +} + +.markdown-body h1 tt, +.markdown-body h1 code, +.markdown-body h2 tt, +.markdown-body h2 code, +.markdown-body h3 tt, +.markdown-body h3 code, +.markdown-body h4 tt, +.markdown-body h4 code, +.markdown-body h5 tt, +.markdown-body h5 code, +.markdown-body h6 tt, +.markdown-body h6 code { + padding: 0 .2em; + font-size: inherit; +} + +.markdown-body summary h1, +.markdown-body summary h2, +.markdown-body summary h3, +.markdown-body summary h4, +.markdown-body summary h5, +.markdown-body summary h6 { + display: inline-block; +} + +.markdown-body summary h1 .anchor, +.markdown-body summary h2 .anchor, +.markdown-body summary h3 .anchor, +.markdown-body summary h4 .anchor, +.markdown-body summary h5 .anchor, +.markdown-body summary h6 .anchor { + margin-left: -40px; +} + +.markdown-body summary h1, +.markdown-body summary h2 { + padding-bottom: 0; + border-bottom: 0; +} + +.markdown-body ul.no-list, +.markdown-body ol.no-list { + padding: 0; + list-style-type: none; +} + +.markdown-body ol[type="a s"] { + list-style-type: lower-alpha; +} + +.markdown-body ol[type="A s"] { + list-style-type: upper-alpha; +} + +.markdown-body ol[type="i s"] { + list-style-type: lower-roman; +} + +.markdown-body ol[type="I s"] { + list-style-type: upper-roman; +} + +.markdown-body ol[type="1"] { + list-style-type: decimal; +} + +.markdown-body div>ol:not([type]) { + list-style-type: decimal; +} + +.markdown-body ul ul, +.markdown-body ul ol, +.markdown-body ol ol, +.markdown-body ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body li>p { + margin-top: var(--base-size-16); +} + +.markdown-body li+li { + margin-top: .25em; +} + +.markdown-body dl { + padding: 0; +} + +.markdown-body dl dt { + padding: 0; + margin-top: var(--base-size-16); + font-size: 1em; + font-style: italic; + font-weight: var(--base-text-weight-semibold, 600); +} + +.markdown-body dl dd { + padding: 0 var(--base-size-16); + margin-bottom: var(--base-size-16); +} + +.markdown-body table th { + font-weight: var(--base-text-weight-semibold, 600); +} + +.markdown-body table th, +.markdown-body table td { + padding: 6px 13px; + border: 1px solid var(--borderColor-default); +} + +.markdown-body table td>:last-child { + margin-bottom: 0; +} + +.markdown-body table tr { + background-color: var(--bgColor-default); + border-top: 1px solid var(--borderColor-muted); +} + +.markdown-body table tr:nth-child(2n) { + background-color: var(--bgColor-muted); +} + +.markdown-body table img { + background-color: transparent; +} + +.markdown-body img[align=right] { + padding-left: 20px; +} + +.markdown-body img[align=left] { + padding-right: 20px; +} + +.markdown-body .emoji { + max-width: none; + vertical-align: text-top; + background-color: transparent; +} + +.markdown-body span.frame { + display: block; + overflow: hidden; +} + +.markdown-body span.frame>span { + display: block; + float: left; + width: auto; + padding: 7px; + margin: 13px 0 0; + overflow: hidden; + border: 1px solid var(--borderColor-default); +} + +.markdown-body span.frame span img { + display: block; + float: left; +} + +.markdown-body span.frame span span { + display: block; + padding: 5px 0 0; + clear: both; + color: var(--fgColor-default); +} + +.markdown-body span.align-center { + display: block; + overflow: hidden; + clear: both; +} + +.markdown-body span.align-center>span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: center; +} + +.markdown-body span.align-center span img { + margin: 0 auto; + text-align: center; +} + +.markdown-body span.align-right { + display: block; + overflow: hidden; + clear: both; +} + +.markdown-body span.align-right>span { + display: block; + margin: 13px 0 0; + overflow: hidden; + text-align: right; +} + +.markdown-body span.align-right span img { + margin: 0; + text-align: right; +} + +.markdown-body span.float-left { + display: block; + float: left; + margin-right: 13px; + overflow: hidden; +} + +.markdown-body span.float-left span { + margin: 13px 0 0; +} + +.markdown-body span.float-right { + display: block; + float: right; + margin-left: 13px; + overflow: hidden; +} + +.markdown-body span.float-right>span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: right; +} + +.markdown-body code, +.markdown-body tt { + padding: .2em .4em; + margin: 0; + font-size: 85%; + white-space: break-spaces; + background-color: var(--bgColor-neutral-muted); + border-radius: 6px; +} + +.markdown-body code br, +.markdown-body tt br { + display: none; +} + +.markdown-body del code { + text-decoration: inherit; +} + +.markdown-body samp { + font-size: 85%; +} + +.markdown-body pre code { + font-size: 100%; +} + +.markdown-body pre>code { + padding: 0; + margin: 0; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.markdown-body .highlight { + margin-bottom: var(--base-size-16); +} + +.markdown-body .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.markdown-body .highlight pre, +.markdown-body pre { + padding: var(--base-size-16); + overflow: auto; + font-size: 85%; + line-height: 1.45; + color: var(--fgColor-default); + background-color: var(--bgColor-muted); + border-radius: 6px; +} + +.markdown-body pre code, +.markdown-body pre tt { + display: inline; + max-width: auto; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.markdown-body .csv-data td, +.markdown-body .csv-data th { + padding: 5px; + overflow: hidden; + font-size: 12px; + line-height: 1; + text-align: left; + white-space: nowrap; +} + +.markdown-body .csv-data .blob-num { + padding: 10px var(--base-size-8) 9px; + text-align: right; + background: var(--bgColor-default); + border: 0; +} + +.markdown-body .csv-data tr { + border-top: 0; +} + +.markdown-body .csv-data th { + font-weight: var(--base-text-weight-semibold, 600); + background: var(--bgColor-muted); + border-top: 0; +} + +.markdown-body [data-footnote-ref]::before { + content: "["; +} + +.markdown-body [data-footnote-ref]::after { + content: "]"; +} + +.markdown-body .footnotes { + font-size: 12px; + color: var(--fgColor-muted); + border-top: 1px solid var(--borderColor-default); +} + +.markdown-body .footnotes ol { + padding-left: var(--base-size-16); +} + +.markdown-body .footnotes ol ul { + display: inline-block; + padding-left: var(--base-size-16); + margin-top: var(--base-size-16); +} + +.markdown-body .footnotes li { + position: relative; +} + +.markdown-body .footnotes li:target::before { + position: absolute; + top: calc(var(--base-size-8)*-1); + right: calc(var(--base-size-8)*-1); + bottom: calc(var(--base-size-8)*-1); + left: calc(var(--base-size-24)*-1); + pointer-events: none; + content: ""; + border: 2px solid var(--borderColor-accent-emphasis); + border-radius: 6px; +} + +.markdown-body .footnotes li:target { + color: var(--fgColor-default); +} + +.markdown-body .footnotes .data-footnote-backref g-emoji { + font-family: monospace; +} + +.markdown-body body:has(:modal) { + padding-right: var(--dialog-scrollgutter) !important; +} + +.markdown-body .pl-c { + color: var(--color-prettylights-syntax-comment); +} + +.markdown-body .pl-c1, +.markdown-body .pl-s .pl-v { + color: var(--color-prettylights-syntax-constant); +} + +.markdown-body .pl-e, +.markdown-body .pl-en { + color: var(--color-prettylights-syntax-entity); +} + +.markdown-body .pl-smi, +.markdown-body .pl-s .pl-s1 { + color: var(--color-prettylights-syntax-storage-modifier-import); +} + +.markdown-body .pl-ent { + color: var(--color-prettylights-syntax-entity-tag); +} + +.markdown-body .pl-k { + color: var(--color-prettylights-syntax-keyword); +} + +.markdown-body .pl-s, +.markdown-body .pl-pds, +.markdown-body .pl-s .pl-pse .pl-s1, +.markdown-body .pl-sr, +.markdown-body .pl-sr .pl-cce, +.markdown-body .pl-sr .pl-sre, +.markdown-body .pl-sr .pl-sra { + color: var(--color-prettylights-syntax-string); +} + +.markdown-body .pl-v, +.markdown-body .pl-smw { + color: var(--color-prettylights-syntax-variable); +} + +.markdown-body .pl-bu { + color: var(--color-prettylights-syntax-brackethighlighter-unmatched); +} + +.markdown-body .pl-ii { + color: var(--color-prettylights-syntax-invalid-illegal-text); + background-color: var(--color-prettylights-syntax-invalid-illegal-bg); +} + +.markdown-body .pl-c2 { + color: var(--color-prettylights-syntax-carriage-return-text); + background-color: var(--color-prettylights-syntax-carriage-return-bg); +} + +.markdown-body .pl-sr .pl-cce { + font-weight: bold; + color: var(--color-prettylights-syntax-string-regexp); +} + +.markdown-body .pl-ml { + color: var(--color-prettylights-syntax-markup-list); +} + +.markdown-body .pl-mh, +.markdown-body .pl-mh .pl-en, +.markdown-body .pl-ms { + font-weight: bold; + color: var(--color-prettylights-syntax-markup-heading); +} + +.markdown-body .pl-mi { + font-style: italic; + color: var(--color-prettylights-syntax-markup-italic); +} + +.markdown-body .pl-mb { + font-weight: bold; + color: var(--color-prettylights-syntax-markup-bold); +} + +.markdown-body .pl-md { + color: var(--color-prettylights-syntax-markup-deleted-text); + background-color: var(--color-prettylights-syntax-markup-deleted-bg); +} + +.markdown-body .pl-mi1 { + color: var(--color-prettylights-syntax-markup-inserted-text); + background-color: var(--color-prettylights-syntax-markup-inserted-bg); +} + +.markdown-body .pl-mc { + color: var(--color-prettylights-syntax-markup-changed-text); + background-color: var(--color-prettylights-syntax-markup-changed-bg); +} + +.markdown-body .pl-mi2 { + color: var(--color-prettylights-syntax-markup-ignored-text); + background-color: var(--color-prettylights-syntax-markup-ignored-bg); +} + +.markdown-body .pl-mdr { + font-weight: bold; + color: var(--color-prettylights-syntax-meta-diff-range); +} + +.markdown-body .pl-ba { + color: var(--color-prettylights-syntax-brackethighlighter-angle); +} + +.markdown-body .pl-sg { + color: var(--color-prettylights-syntax-sublimelinter-gutter-mark); +} + +.markdown-body .pl-corl { + text-decoration: underline; + color: var(--color-prettylights-syntax-constant-other-reference-link); +} + +.markdown-body [role=button]:focus:not(:focus-visible), +.markdown-body [role=tabpanel][tabindex="0"]:focus:not(:focus-visible), +.markdown-body button:focus:not(:focus-visible), +.markdown-body summary:focus:not(:focus-visible), +.markdown-body a:focus:not(:focus-visible) { + outline: none; + box-shadow: none; +} + +.markdown-body [tabindex="0"]:focus:not(:focus-visible), +.markdown-body details-dialog:focus:not(:focus-visible) { + outline: none; +} + +.markdown-body g-emoji { + display: inline-block; + min-width: 1ch; + font-family: "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + font-size: 1em; + font-style: normal !important; + font-weight: var(--base-text-weight-normal, 400); + line-height: 1; + vertical-align: -0.075em; +} + +.markdown-body g-emoji img { + width: 1em; + height: 1em; +} + +.markdown-body .task-list-item { + list-style-type: none; +} + +.markdown-body .task-list-item label { + font-weight: var(--base-text-weight-normal, 400); +} + +.markdown-body .task-list-item.enabled label { + cursor: pointer; +} + +.markdown-body .task-list-item+.task-list-item { + margin-top: var(--base-size-4); +} + +.markdown-body .task-list-item .handle { + display: none; +} + +.markdown-body .task-list-item-checkbox { + margin: 0 .2em .25em -1.4em; + vertical-align: middle; +} + +.markdown-body ul:dir(rtl) .task-list-item-checkbox { + margin: 0 -1.6em .25em .2em; +} + +.markdown-body ol:dir(rtl) .task-list-item-checkbox { + margin: 0 -1.6em .25em .2em; +} + +.markdown-body .contains-task-list:hover .task-list-item-convert-container, +.markdown-body .contains-task-list:focus-within .task-list-item-convert-container { + display: block; + width: auto; + height: 24px; + overflow: visible; + clip: auto; +} + +.markdown-body ::-webkit-calendar-picker-indicator { + filter: invert(50%); +} + +.markdown-body .markdown-alert { + padding: var(--base-size-8) var(--base-size-16); + margin-bottom: var(--base-size-16); + color: inherit; + border-left: .25em solid var(--borderColor-default); +} + +.markdown-body .markdown-alert>:first-child { + margin-top: 0; +} + +.markdown-body .markdown-alert>:last-child { + margin-bottom: 0; +} + +.markdown-body .markdown-alert .markdown-alert-title { + display: flex; + font-weight: var(--base-text-weight-medium, 500); + align-items: center; + line-height: 1; +} + +.markdown-body .markdown-alert.markdown-alert-note { + border-left-color: var(--borderColor-accent-emphasis); +} + +.markdown-body .markdown-alert.markdown-alert-note .markdown-alert-title { + color: var(--fgColor-accent); +} + +.markdown-body .markdown-alert.markdown-alert-important { + border-left-color: var(--borderColor-done-emphasis); +} + +.markdown-body .markdown-alert.markdown-alert-important .markdown-alert-title { + color: var(--fgColor-done); +} + +.markdown-body .markdown-alert.markdown-alert-warning { + border-left-color: var(--borderColor-attention-emphasis); +} + +.markdown-body .markdown-alert.markdown-alert-warning .markdown-alert-title { + color: var(--fgColor-attention); +} + +.markdown-body .markdown-alert.markdown-alert-tip { + border-left-color: var(--borderColor-success-emphasis); +} + +.markdown-body .markdown-alert.markdown-alert-tip .markdown-alert-title { + color: var(--fgColor-success); +} + +.markdown-body .markdown-alert.markdown-alert-caution { + border-left-color: var(--borderColor-danger-emphasis); +} + +.markdown-body .markdown-alert.markdown-alert-caution .markdown-alert-title { + color: var(--fgColor-danger); +} + +.markdown-body>*:first-child>.heading-element:first-child { + margin-top: 0 !important; +} + +.markdown-body ul[role='list'], +.markdown-body ol[role='list'] { + list-style: none; +} + +.markdown-body html[focus-within] { + scroll-behavior: smooth; +} + +.markdown-body html:focus-within { + scroll-behavior: smooth; +} + +.markdown-body a:not([class]) { + -webkit-text-decoration-skip: ink; + text-decoration-skip-ink: auto; +} + +.markdown-body img, +.markdown-body picture { + max-width: 100%; + display: block; +} + +.markdown-body [class^=Primer_Brand__Link-module__Link___]::after { + width: calc(100% - 20px); +} + diff --git a/generatedDocs/levels.html b/generatedDocs/levels.html index 73636ef0..80425673 100755 --- a/generatedDocs/levels.html +++ b/generatedDocs/levels.html @@ -3,8 +3,1263 @@ Learn Git Branching - Level Documentation + -

Learn Git Branching - Level Documentation

+
+

Learn Git Branching - All Levels Documentation

-
-

Multiple parents

- -

Goal Tree:

-
{"branches":{"main":{"target":"C7","id":"main"},"bugWork":{"target":"C2","id":"bugWork"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C4","C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"main","id":"HEAD"}}
- -

Solution:

-
git branch bugWork main^^2^
- -

Hint:

-

Use `git branch bugWork` with a target commit to create the missing reference.

-
- -
-

Branching in Git

- -

Goal Tree:

-
{"branches":{"main":{"target":"C1","id":"main"},"bugFix":{"target":"C1","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"bugFix","id":"HEAD"}}
- -

Solution:

-
git branch bugFix;git checkout bugFix
- -

Hint:

-

Make a new branch with "git branch " and check it out with "git checkout "

-
- -
-

Introduction to Git Commits

- -

Goal Tree:

-
{"branches":{"main":{"target":"C3","id":"main"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"main","id":"HEAD"}}
- -

Solution:

-
git commit;git commit
- -

Hint:

-

Just type in 'git commit' twice to finish!

-
- -
-

Merging in Git

- -

Goal Tree:

-
{"branches":{"main":{"target":"C4","id":"main"},"bugFix":{"target":"C2","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3","C2"],"id":"C4"}},"HEAD":{"target":"main","id":"HEAD"}}
- -

Solution:

-
git checkout -b bugFix;git commit;git checkout main;git commit;git merge bugFix
- -

Hint:

-

Remember to commit in the order specified (bugFix before main)

-
- -
-

Rebase Introduction

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22main%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22bugFix%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git checkout -b bugFix;git commit;git checkout main;git commit;git checkout bugFix;git rebase main
- -

Hint:

-

Make sure you commit from bugFix first

-
- -
-

Git Describe

- -

Goal Tree:

-
{"branches":{"main":{"target":"C2","id":"main","remoteTrackingBranchID":null},"side":{"target":"C4","id":"side","remoteTrackingBranchID":null},"bugFix":{"target":"C7","id":"bugFix","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"tags":{"v0":{"target":"C0","id":"v0","type":"tag"},"v1":{"target":"C3","id":"v1","type":"tag"}},"HEAD":{"target":"bugFix","id":"HEAD"}}
- -

Solution:

-
git commit 
- -

Hint:

-

Just commit once on bugFix when you're ready to move on

-
- -
-

Grabbing Just 1 Commit

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22main%22%7D%2C%22debug%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22debug%22%7D%2C%22printf%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22printf%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22bugFix%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git rebase -i main --solution-ordering C4; git rebase bugFix main
- -

Hint:

-

Remember, interactive rebase or cherry-pick is your friend here

-
- -
-

Juggling Commits

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22main%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%27%27%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C2%27%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git rebase -i HEAD~2 --solution-ordering C3,C2;git commit --amend;git rebase -i HEAD~2 --solution-ordering C2'',C3';git rebase caption main
- -

Hint:

-

The first command is git rebase -i HEAD~2

-
- -
-

Juggling Commits #2

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22main%22%7D%2C%22newImage%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22newImage%22%7D%2C%22caption%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22caption%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git checkout main;git cherry-pick C2;git commit --amend;git cherry-pick C3
- -

Hint:

-

Don't forget to forward main to the updated changes!

-
- -
-

Git Tags

- -

Goal Tree:

-
{"branches":{"main":{"target":"C5","id":"main","remoteTrackingBranchID":null},"side":{"target":"C3","id":"side","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C1"],"id":"C4"},"C5":{"parents":["C2","C4"],"id":"C5"}},"tags":{"v1":{"target":"C2","id":"v1","type":"tag"},"v0":{"target":"C1","id":"v0","type":"tag"}},"HEAD":{"target":"C2","id":"HEAD"}}
- -

Solution:

-
git tag v1 side~1;git tag v0 main~2;git checkout v1
- -

Hint:

-

you can either check out the commit directly or simply checkout the tag!

-
- -
-

Cherry-pick Intro

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22main%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C6%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git cherry-pick C3 C4 C7
- -

Hint:

-

git cherry-pick followed by commit names!

-
- -
-

Detach yo' HEAD

- -

Goal Tree:

-
{"branches":{"main":{"target":"C2","id":"main"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C4","id":"HEAD"}}
- -

Solution:

-
git checkout C4
- -

Hint:

-

Use the label (hash) on the commit for help!

-
- -
-

Interactive Rebase Intro

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22main%22%7D%2C%22overHere%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22overHere%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git rebase -i overHere --solution-ordering C3,C5,C4
- -

Hint:

-

you can use either branches or relative refs (HEAD~) to specify the rebase target

-
- -
-

Relative Refs (^)

- -

Goal Tree:

-
{"branches":{"main":{"target":"C2","id":"main"},"bugFix":{"target":"C4","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"}},"HEAD":{"target":"C3","id":"HEAD"}}
- -

Solution:

-
git checkout bugFix^
- -

Hint:

-

Remember the Caret (^) operator!

-
- -
-

Relative Refs #2 (~)

- -

Goal Tree:

-
{"branches":{"main":{"target":"C6","id":"main"},"bugFix":{"target":"C0","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C3"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"C1","id":"HEAD"}}
- -

Solution:

-
git branch -f main C6;git checkout HEAD~1;git branch -f bugFix HEAD~1
- -

Hint:

-

You'll need to use at least one direct reference (hash) to complete this level

-
- -
-

Reversing Changes in Git

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22main%22%7D%2C%22pushed%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22pushed%22%7D%2C%22local%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22local%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C2%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22pushed%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git reset HEAD~1;git checkout pushed;git revert HEAD
- -

Hint:

-

Notice that revert and reset take different arguments.

-
- -
-

Rebasing over 9000 times

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22main%22%7D%2C%22bugFix%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22bugFix%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C6%27%22%2C%22id%22%3A%22side%22%7D%2C%22another%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22another%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git rebase main bugFix;git rebase bugFix side;git rebase side another;git rebase another main
- -

Hint:

-

Remember, the most efficient way might be to only update main at the end...

-
- -
-

Branch Spaghetti

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C5%22%2C%22id%22%3A%22main%22%7D%2C%22one%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22one%22%7D%2C%22two%22%3A%7B%22target%22%3A%22C2%27%27%22%2C%22id%22%3A%22two%22%7D%2C%22three%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22three%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C4%27%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C4%27%27%22%7D%2C%22C3%27%27%22%3A%7B%22parents%22%3A%5B%22C4%27%27%22%5D%2C%22id%22%3A%22C3%27%27%22%7D%2C%22C2%27%27%22%3A%7B%22parents%22%3A%5B%22C3%27%27%22%5D%2C%22id%22%3A%22C2%27%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22two%22%2C%22id%22%3A%22HEAD%22%7D%7D
- -

Solution:

-
git checkout one; git cherry-pick C4 C3 C2; git checkout two; git cherry-pick C5 C4 C3 C2; git branch -f three C2
- -

Hint:

-

Make sure to do everything in the proper order! Branch one first, then two, then three

-
- -
-

Clone Intro

- -

Goal Tree:

-
{"branches":{"main":{"target":"C1","id":"main","remoteTrackingBranchID":"o/main"},"o/main":{"target":"C1","id":"o/main","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C1","id":"main","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git clone
- -

Hint:

-

Just git clone!

-
- -
-

Faking Teamwork

- -

Goal Tree:

-
{"branches":{"main":{"target":"C5","id":"main","remoteTrackingBranchID":"o/main","localBranchesThatTrackThis":null},"o/main":{"target":"C3","id":"o/main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":["main"]}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C4":{"parents":["C1"],"id":"C4"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C5":{"parents":["C3","C4"],"id":"C5"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C3","id":"main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git clone;git fakeTeamwork 2;git commit ;git pull
- -

Hint:

-

Remember you can specify the number of commits to fake

-
- -
-

Git Fetchin'

- -

Goal Tree:

-
{"branches":{"main":{"target":"C2","id":"main"},"bugFix":{"target":"C3","id":"bugFix"},"o/main":{"target":"C5","id":"o/main"},"o/bugFix":{"target":"C7","id":"o/bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C6":{"parents":["C3"],"id":"C6"},"C5":{"parents":["C4"],"id":"C5"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"bugFix","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C5","id":"main"},"bugFix":{"target":"C7","id":"bugFix"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2"],"id":"C4"},"C5":{"parents":["C4"],"id":"C5"},"C6":{"parents":["C3"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"}},"HEAD":{"target":"bugFix","id":"HEAD"}}}
- -

Solution:

-
git fetch
- -

Hint:

-

just run git fetch!

-
- -
-

Fetch arguments

- -

Goal Tree:

-
{"branches":{"main":{"target":"C6","id":"main","remoteTrackingBranchID":"o/main"},"foo":{"target":"C7","id":"foo","remoteTrackingBranchID":"o/foo"},"o/main":{"target":"C1","id":"o/main","remoteTrackingBranchID":null},"o/foo":{"target":"C1","id":"o/foo","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C5":{"parents":["C1"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C3","C6"],"id":"C7"}},"HEAD":{"target":"foo","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C4","id":"main","remoteTrackingBranchID":null},"foo":{"target":"C6","id":"foo","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C1"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"foo","id":"HEAD"}}}
- -

Solution:

-
git fetch origin c3:foo;git fetch origin c6:main;git checkout foo;git merge main
- -

Hint:

-

Pay attention how the commit ids may have swapped! You can read slides again with "help level"

-
- -
-

Diverged History

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3A%22o/main%22%2C%22localBranchesThatTrackThis%22%3Anull%7D%2C%22o/main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22o/main%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3A%5B%22main%22%5D%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%2C%22originTree%22%3A%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3Anull%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D%7D
- -

Solution:

-
git clone;git fakeTeamwork;git commit;git pull --rebase;git push
- -

Hint:

-

Check out the ordering from the goal visualization

-
- -
-

Locked Main

- -

Goal Tree:

-
{"branches":{"main":{"target":"C1","id":"main","remoteTrackingBranchID":"o/main"},"o/main":{"target":"C1","id":"o/main","remoteTrackingBranchID":null},"feature":{"target":"C2","id":"feature","remoteTrackingBranchID":"o/feature"},"o/feature":{"target":"C2","id":"o/feature","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"tags":{},"HEAD":{"target":"feature","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C1","id":"main","remoteTrackingBranchID":null},"feature":{"target":"C2","id":"feature","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"tags":{},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git branch -f main o/main; git checkout -b feature C2; git push origin feature
- -

Hint:

-

Make the feature branch from the local main before resetting it back to be the same as origin's main

-
- -
-

Merging with remotes

- -

Goal Tree:

-
{"branches":{"main":{"target":"C11","id":"main","remoteTrackingBranchID":"o/main","localBranchesThatTrackThis":null},"o/main":{"target":"C11","id":"o/main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":["main"]},"side1":{"target":"C2","id":"side1","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null},"side2":{"target":"C4","id":"side2","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null},"side3":{"target":"C7","id":"side3","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C3"],"id":"C4"},"C5":{"parents":["C1"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"},"C7":{"parents":["C6"],"id":"C7"},"C8":{"parents":["C1"],"id":"C8"},"C9":{"parents":["C2","C8"],"id":"C9"},"C10":{"parents":["C4","C9"],"id":"C10"},"C11":{"parents":["C10","C7"],"id":"C11"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C11","id":"main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C8":{"parents":["C1"],"id":"C8"},"C5":{"parents":["C1"],"id":"C5"},"C3":{"parents":["C1"],"id":"C3"},"C2":{"parents":["C1"],"id":"C2"},"C6":{"parents":["C5"],"id":"C6"},"C4":{"parents":["C3"],"id":"C4"},"C9":{"parents":["C2","C8"],"id":"C9"},"C7":{"parents":["C6"],"id":"C7"},"C10":{"parents":["C4","C9"],"id":"C10"},"C11":{"parents":["C10","C7"],"id":"C11"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git checkout main;git pull;git merge side1;git merge side2;git merge side3;git push
- -

Hint:

-

Pay attention to the goal tree!

-
- -
-

Git Pullin'

- -

Goal Tree:

-
{"branches":{"main":{"target":"C4","id":"main","remoteTrackingBranchID":"o/main","localBranchesThatTrackThis":null},"o/main":{"target":"C3","id":"o/main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":["main"]}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2","C3"],"id":"C4"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C3","id":"main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git pull
- -

Hint:

-

Just run git pull!

-
- -
-

Pull arguments

- -

Goal Tree:

-
{"branches":{"main":{"target":"C6","id":"main","remoteTrackingBranchID":"o/main"},"o/main":{"target":"C1","id":"o/main","remoteTrackingBranchID":null},"o/bar":{"target":"C1","id":"o/bar","remoteTrackingBranchID":null},"foo":{"target":"C3","id":"foo","remoteTrackingBranchID":null},"side":{"target":"C2","id":"side","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C4":{"parents":["C1"],"id":"C4"},"C3":{"parents":["C1"],"id":"C3"},"C5":{"parents":["C3","C4"],"id":"C5"},"C2":{"parents":["C1"],"id":"C2"},"C6":{"parents":["C2","C5"],"id":"C6"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C2","id":"main","remoteTrackingBranchID":null},"bar":{"target":"C3","id":"bar","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"bar","id":"HEAD"}}}
- -

Solution:

-
git pull origin c3:foo;git pull origin c2:side
- -

Hint:

-

Remember that you can create new local branches with fetch/pull arguments

-
- -
-

Git Pushin'

- -

Goal Tree:

-
{"branches":{"main":{"target":"C3","id":"main","remoteTrackingBranchID":"o/main","localBranchesThatTrackThis":null},"o/main":{"target":"C3","id":"o/main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":["main"]}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C3","id":"main","remoteTrackingBranchID":null,"localBranchesThatTrackThis":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git commit;git commit;git push
- -

Hint:

-

Remember you have to clone before you can push!

-
- -
-

Git push arguments

- -

Goal Tree:

-
{"branches":{"main":{"target":"C2","id":"main","remoteTrackingBranchID":"o/main"},"foo":{"target":"C3","id":"foo","remoteTrackingBranchID":"o/foo"},"o/main":{"target":"C2","id":"o/main","remoteTrackingBranchID":null},"o/foo":{"target":"C3","id":"o/foo","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"C0","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C2","id":"main","remoteTrackingBranchID":null},"foo":{"target":"C3","id":"foo","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git push origin main;git push origin foo
- -

Hint:

-

You can always look at the last slide of the dialog with "objective"

-
- -
-

Git push arguments -- Expanded!

- -

Goal Tree:

-
{"branches":{"main":{"target":"C6","id":"main","remoteTrackingBranchID":"o/main"},"foo":{"target":"C4","id":"foo","remoteTrackingBranchID":"o/foo"},"o/main":{"target":"C4","id":"o/main","remoteTrackingBranchID":null},"o/foo":{"target":"C5","id":"o/foo","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2","C3"],"id":"C4"},"C5":{"parents":["C2"],"id":"C5"},"C6":{"parents":["C5"],"id":"C6"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C4","id":"main","remoteTrackingBranchID":null},"foo":{"target":"C5","id":"foo","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C5":{"parents":["C2"],"id":"C5"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C2","C3"],"id":"C4"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git push origin main^:foo;git push origin foo:main
- -

Hint:

-

Remember you can admit defeat and type in "show solution" :P

-
- -
-

Push Main!

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3A%22o/main%22%2C%22localBranchesThatTrackThis%22%3Anull%7D%2C%22o/main%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22o/main%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3A%5B%22main%22%5D%7D%2C%22side1%22%3A%7B%22target%22%3A%22C2%27%22%2C%22id%22%3A%22side1%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3Anull%7D%2C%22side2%22%3A%7B%22target%22%3A%22C4%27%22%2C%22id%22%3A%22side2%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3Anull%7D%2C%22side3%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22side3%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3Anull%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C7%22%3A%7B%22parents%22%3A%5B%22C6%22%5D%2C%22id%22%3A%22C7%22%7D%2C%22C8%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C8%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C8%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%2C%22originTree%22%3A%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C7%27%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3Anull%2C%22localBranchesThatTrackThis%22%3Anull%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C8%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C8%22%7D%2C%22C2%27%22%3A%7B%22parents%22%3A%5B%22C8%22%5D%2C%22id%22%3A%22C2%27%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%27%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C5%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C5%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C5%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%2C%22C7%27%22%3A%7B%22parents%22%3A%5B%22C6%27%22%5D%2C%22id%22%3A%22C7%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D%7D
- -

Solution:

-
git fetch;git rebase o/main side1;git rebase side1 side2;git rebase side2 side3;git rebase side3 main;git push
- -

Hint:

-

Remember you can always use the undo or reset commands

-
- -
-

Remote Branches

- -

Goal Tree:

-
{"branches":{"main":{"target":"C3","id":"main"},"o/main":{"target":"C1","id":"o/main"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C3":{"parents":["C1"],"id":"C3"},"C4":{"parents":["C1"],"id":"C4"}},"HEAD":{"target":"C4","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C2","id":"main"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git commit;git checkout o/main;git commit
- -

Hint:

-

Pay attention to the ordering -- commit on main first!

-
- -
-

Source of nothing

- -

Goal Tree:

-
{"branches":{"main":{"target":"C1","id":"main","remoteTrackingBranchID":"o/main"},"o/main":{"target":"C1","id":"o/main","remoteTrackingBranchID":null},"bar":{"target":"C1","id":"bar","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"main","id":"HEAD"},"originTree":{"branches":{"main":{"target":"C1","id":"main","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"main","id":"HEAD"}}}
- -

Solution:

-
git push origin :foo;git fetch origin :bar
- -

Hint:

-

The branch command is disabled for this level so you'll have to use fetch!

-
- -
-

Remote Tracking

- -

Goal Tree:

-
%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3A%22o/main%22%7D%2C%22o/main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22o/main%22%2C%22remoteTrackingBranchID%22%3Anull%7D%2C%22side%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22side%22%2C%22remoteTrackingBranchID%22%3A%22o/main%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22side%22%2C%22id%22%3A%22HEAD%22%7D%2C%22originTree%22%3A%7B%22branches%22%3A%7B%22main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3Anull%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22main%22%2C%22id%22%3A%22HEAD%22%7D%7D%7D
- -

Solution:

-
git checkout -b side o/main;git commit;git pull --rebase;git push
- -

Hint:

-

Remember there are two ways to set remote tracking!

-
- +

Level Sequence: Introduction Sequence

+
A nicely paced introduction to the majority of git commands
+

Level: Introduction to Git Commits

Git Commits

+

A commit in a git repository records a snapshot of all the (tracked) files in your directory. It's like a giant copy and paste, but even better!

+

Git wants to keep commits as lightweight as possible though, so it doesn't just blindly copy the entire directory every time you commit. It can (when possible) compress a commit as a set of changes, or a "delta", from one version of the repository to the next.

+

Git also maintains a history of which commits were made when. That's why most commits have ancestor commits above them -- we designate this with arrows in our visualization. Maintaining history is great for everyone working on the project!

+

It's a lot to take in, but for now you can think of commits as snapshots of the project. Commits are very lightweight and switching between them is wicked fast!

+

Let's see what this looks like in practice. On the right we have a visualization of a (small) git repository. There are two commits right now -- the first initial commit, C0, and one commit after that C1 that might have some meaningful changes.

+

Hit the button below to make a new commit.

+
git commit

There we go! Awesome. We just made changes to the repository and saved them as a commit. The commit we just made has a parent, C1, which references which commit it was based off of.

+

Go ahead and try it out on your own! After this window closes, make two commits to complete the level.

+

Level: Branching in Git

Git Branches

+

Branches in Git are incredibly lightweight as well. They are simply pointers to a specific commit -- nothing more. This is why many Git enthusiasts chant the mantra:

+
branch early, and branch often
+
+

Because there is no storage / memory overhead with making many branches, it's easier to logically divide up your work than have big beefy branches.

+

When we start mixing branches and commits, we will see how these two features combine. For now though, just remember that a branch essentially says "I want to include the work of this commit and all parent commits."

+

Let's see what branches look like in practice.

+

Here we will create a new branch named newImage.

+
git branch newImage

There, that's all there is to branching! The branch newImage now refers to commit C1.

+

Let's try to put some work on this new branch. Hit the button below.

+
git commit

Oh no! The main branch moved but the newImage branch didn't! That's because we weren't "on" the new branch, which is why the asterisk (*) was on main.

+

Let's tell git we want to checkout the branch with

+
git checkout <name>
+
+

This will put us on the new branch before committing our changes.

+
git checkout newImage; git commit

There we go! Our changes were recorded on the new branch.

+

Note: In Git version 2.23, a new command called git switch was introduced to eventually replace git checkout, +which is somewhat overloaded (it does a bunch of different things depending on the arguments). The lessons here will still use +checkout instead of switch because the switch command is still considered experimental and the syntax may change in the future. +However you can still try out the new switch command in this application, and also +learn more here.

+

Ok! You are all ready to get branching. Once this window closes, +make a new branch named bugFix and switch to that branch.

+

By the way, here's a shortcut: if you want to create a new +branch AND check it out at the same time, you can simply +type git checkout -b [yourbranchname].

+

Level: Merging in Git

Branches and Merging

+

Great! We now know how to commit and branch. Now we need to learn some kind of way of combining the work from two different branches together. This will allow us to branch off, develop a new feature, and then combine it back in.

+

The first method to combine work that we will examine is git merge. Merging in Git creates a special commit that has two unique parents. A commit with two parents essentially means "I want to include all the work from this parent over here and this one over here, and the set of all their parents."

+

It's easier with visuals, let's check it out in the next view.

+

Here we have two branches; each has one commit that's unique. This means that neither branch includes the entire set of "work" in the repository that we have done. Let's fix that with merge.

+

We will merge the branch bugFix into main.

+
git merge bugFix

Woah! See that? First of all, main now points to a commit that has two parents. If you follow the arrows up the commit tree from main, you will hit every commit along the way to the root. This means that main contains all the work in the repository now.

+

Also, see how the colors of the commits changed? To help with learning, I have included some color coordination. Each branch has a unique color. Each commit turns a color that is the blended combination of all the branches that contain that commit.

+

So here we see that the main branch color is blended into all the commits, but the bugFix color is not. Let's fix that...

+

Let's merge main into bugFix:

+
git checkout bugFix; git merge main

Since bugFix was an ancestor of main, git didn't have to do any work; it simply just moved bugFix to the same commit main was attached to.

+

Now all the commits are the same color, which means each branch contains all the work in the repository! Woohoo!

+

To complete this level, do the following steps:

+ +

Remember, you can always re-display this dialog with "objective"!

+

Level: Rebase Introduction

Git Rebase

+

The second way of combining work between branches is rebasing. Rebasing essentially takes a set of commits, "copies" them, and plops them down somewhere else.

+

While this sounds confusing, the advantage of rebasing is that it can be used to make a nice linear sequence of commits. The commit log / history of the repository will be a lot cleaner if only rebasing is allowed.

+

Let's see it in action...

+

Here we have two branches yet again; note that the bugFix branch is currently selected (note the asterisk)

+

We would like to move our work from bugFix directly onto the work from main. That way it would look like these two features were developed sequentially, when in reality they were developed in parallel.

+

Let's do that with the git rebase command.

+
git rebase main

Awesome! Now the work from our bugFix branch is right on top of main and we have a nice linear sequence of commits.

+

Note that the commit C3 still exists somewhere (it has a faded appearance in the tree), and C3' is the "copy" that we rebased onto main.

+

The only problem is that main hasn't been updated either, let's do that now...

+

Now we are checked out on the main branch. Let's go ahead and rebase onto bugFix...

+
git rebase bugFix

There! Since main was an ancestor of bugFix, git simply moved the main branch reference forward in history.

+

To complete this level, do the following

+ +

Good luck!

+ +

Level Sequence: Ramping Up

+
The next serving of 100% git awesomes-ness. Hope you're hungry
+

Level: Detach yo' HEAD

Moving around in Git

+

Before we get to some of the more advanced features of Git, it's important to understand different ways to move through the commit tree that represents your project.

+

Once you're comfortable moving around, your powers with other git commands will be amplified!

+ +

First we have to talk about "HEAD". HEAD is the symbolic name for the currently checked out commit -- it's essentially what commit you're working on top of.

+

HEAD always points to the most recent commit which is reflected in the working tree. Most git commands which make changes to the working tree will start by changing HEAD.

+

Normally HEAD points to a branch name (like bugFix). When you commit, the status of bugFix is altered and this change is visible through HEAD.

+

Let's see this in action. Here we will reveal HEAD before and after a commit.

+
git checkout C1; git checkout main; git commit; git checkout C2

See! HEAD was hiding underneath our main branch all along.

+

Detaching HEAD

+

Detaching HEAD just means attaching it to a commit instead of a branch. This is what it looks like beforehand:

+

HEAD -> main -> C1

+
git checkout C1

And now it's

+

HEAD -> C1

+

To complete this level, let's detach HEAD from bugFix and attach it to the commit instead.

+

Specify this commit by its hash. The hash for each commit is displayed on the circle that represents the commit.

+

Level: Relative Refs (^)

Relative Refs

+

Moving around in Git by specifying commit hashes can get a bit tedious. In the real world you won't have a nice commit tree visualization next to your terminal, so you'll have to use git log to see hashes.

+

Furthermore, hashes are usually a lot longer in the real Git world as well. For instance, the hash of the commit that introduced the previous level is fed2da64c0efc5293610bdd892f82a58e8cbc5d8. Doesn't exactly roll off the tongue...

+

The upside is that Git is smart about hashes. It only requires you to specify enough characters of the hash until it uniquely identifies the commit. So I can type fed2 instead of the long string above.

+

Like I said, specifying commits by their hash isn't the most convenient thing ever, which is why Git has relative refs. They are awesome!

+

With relative refs, you can start somewhere memorable (like the branch bugFix or HEAD) and work from there.

+

Relative commits are powerful, but we will introduce two simple ones here:

+ +

Let's look at the Caret (^) operator first. Each time you append that to a ref name, you are telling Git to find the parent of the specified commit.

+

So saying main^ is equivalent to "the first parent of main".

+

main^^ is the grandparent (second-generation ancestor) of main

+

Let's check out the commit above main here.

+
git checkout main^

Boom! Done. Way easier than typing the commit hash.

+

You can also reference HEAD as a relative ref. Let's use that a couple of times to move upwards in the commit tree.

+
git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^

Easy! We can travel backwards in time with HEAD^

+

To complete this level, check out the parent commit of bugFix. This will detach HEAD.

+

You can specify the hash if you want, but try using relative refs instead!

+

Level: Relative Refs #2 (~)

The "~" operator

+

Say you want to move a lot of levels up in the commit tree. It might be tedious to type ^ several times, so Git also has the tilde (~) operator.

+

The tilde operator (optionally) takes in a trailing number that specifies the number of parents you would like to ascend. Let's see it in action.

+

Let's specify a number of commits back with ~.

+
git checkout HEAD~4

Boom! So concise -- relative refs are great.

+

Branch forcing

+

You're an expert on relative refs now, so let's actually use them for something.

+

One of the most common ways I use relative refs is to move branches around. You can directly reassign a branch to a commit with the -f option. So something like:

+

git branch -f main HEAD~3

+

moves (by force) the main branch to three parents behind HEAD.

+

Note: In a real git environment git branch -f command is not allowed for your current branch.

+

Let's see that previous command in action.

+
git branch -f main HEAD~3

There we go! Relative refs gave us a concise way to refer to C1 and branch forcing (-f) gave us a way to quickly move a branch to that location.

+

Now that you have seen relative refs and branch forcing in combination, let's use them to solve the next level.

+

To complete this level, move HEAD, main, and bugFix to their goal destinations shown.

+

Level: Reversing Changes in Git

Reversing Changes in Git

+

There are many ways to reverse changes in Git. And just like committing, reversing changes in Git has both a low-level component (staging individual files or chunks) and a high-level component (how the changes are actually reversed). Our application will focus on the latter.

+

There are two primary ways to undo changes in Git -- one is using git reset and the other is using git revert. We will look at each of these in the next dialog

+

Git Reset

+

git reset reverses changes by moving a branch reference backwards in time to an older commit. In this sense you can think of it as "rewriting history;" git reset will move a branch backwards as if the commit had never been made in the first place.

+

Let's see what that looks like:

+
git reset HEAD~1

Nice! Git moved the main branch reference back to C1; now our local repository is in a state as if C2 had never happened.

+

Git Revert

+

While resetting works great for local branches on your own machine, its method of "rewriting history" doesn't work for remote branches that others are using.

+

In order to reverse changes and share those reversed changes with others, we need to use git revert. Let's see it in action.

+
git revert HEAD

Weird, a new commit plopped down below the commit we wanted to reverse. That's because this new commit C2' introduces changes -- it just happens to introduce changes that exactly reverses the commit of C2.

+

With reverting, you can push out your changes to share with others.

+

To complete this level, reverse the most recent commit on both local and pushed. You will revert two commits total (one per branch).

+

Keep in mind that pushed is a remote branch and local is a local branch -- that should help you choose your methods.

+ +

Level Sequence: Push & Pull -- Git Remotes!

+
Time to share your 1's and 0's kids; coding just got social
+

Level: Clone Intro

Git Remotes

+

Remote repositories aren't actually that complicated. In today's world of cloud computing it's easy to think that there's a lot of magic behind git remotes, but they are actually just copies of your repository on another computer. You can typically talk to this other computer through the Internet, which allows you to transfer commits back and forth.

+

That being said, remote repositories have a bunch of great properties:

+ +

It's become very popular to use websites that visualize activity around remote repos (like GitHub), but remote repositories always serve as the underlying backbone for these tools. So it's important to understand them!

+

Our Command to create remotes

+

Up until this point, Learn Git Branching has focused on teaching the basics of local repository work (branching, merging, rebasing, etc). However now that we want to learn about remote repository work, we need a command to set up the environment for those lessons. git clone will be that command.

+

Technically, git clone in the real world is the command you'll use to create local copies of remote repositories (from github for example). We use this command a bit differently in Learn Git Branching though -- git clone actually makes a remote repository out of your local one. Sure it's technically the opposite meaning of the real command, but it helps build the connection between cloning and remote repository work, so let's just run with it for now.

+

Lets start slow and just look at what a remote repository looks like (in our visualization).

+
git clone

There it is! Now we have a remote repository of our project. It looks pretty similar except for some visual changes to make the distinction apparent -- in later levels you'll get to see how we share work across these repositories.

+

To finish this level, simply git clone your existing repository. The real learning will come in following lessons.

+

Level: Remote Branches

Git Remote Branches

+

Now that you've seen git clone in action, let's dive into what actually changed.

+

The first thing you may have noticed is that a new branch appeared in our local repository called o/main. This type of branch is called a remote branch; remote branches have special properties because they serve a unique purpose.

+

Remote branches reflect the state of remote repositories (since you last talked to those remote repositories). They help you understand the difference between your local work and what work is public -- a critical step to take before sharing your work with others.

+

Remote branches have the special property that when you check them out, you are put into detached HEAD mode. Git does this on purpose because you can't work on these branches directly; you have to work elsewhere and then share your work with the remote (after which your remote branches will be updated).

+

To be clear: Remote branches are on your local repository, not on the remote repository.

+

What is o/?

+

You may be wondering what the leading o/ is for on these remote branches. Well, remote branches also have a (required) naming convention -- they are displayed in the format of:

+ +

Hence, if you look at a branch named o/main, the branch name is main and the name of the remote is o.

+

Most developers actually name their main remote origin, not o. This is so common that git actually sets up your remote to be named origin when you git clone a repository.

+

Unfortunately the full name of origin does not fit in our UI, so we use o as shorthand :( Just remember when you're using real git, your remote is probably going to be named origin!

+

That's a lot to take in, so let's see all this in action.

+

Lets check out a remote branch and see what happens.

+
git checkout o/main; git commit

As you can see, git put us into detached HEAD mode and then did not update o/main when we added a new commit. This is because o/main will only update when the remote updates.

+

To finish this level, commit once off of main and once after checking out o/main. This will help drive home how remote branches behave differently, and they only update to reflect the state of the remote.

+

Level: Git Fetchin'

Git Fetch

+

Working with git remotes really just boils down to transferring data to and from other repositories. As long as we can send commits back and forth, we can share any type of update that is tracked by git (and thus share work, new files, new ideas, love letters, etc.).

+

In this lesson we will learn how to fetch data from a remote repository -- the command for this is conveniently named git fetch.

+

You'll notice that as we update our representation of the remote repository, our remote branches will update to reflect that new representation. This ties into the previous lesson on remote branches.

+

Before getting into the details of git fetch, let's see it in action! Here we have a remote repository that contains two commits that our local repository does not have.

+
git fetch

There we go! Commits C2 and C3 were downloaded to our local repository, and our remote branch o/main was updated to reflect this.

+

What fetch does

+

git fetch performs two main steps, and two main steps only. It:

+ +

git fetch essentially brings our local representation of the remote repository into synchronization with what the actual remote repository looks like (right now).

+

If you remember from the previous lesson, we said that remote branches reflect the state of the remote repositories since you last talked to those remotes. git fetch is the way you talk to these remotes! Hopefully the connection between remote branches and git fetch is apparent now.

+

git fetch usually talks to the remote repository through the Internet (via a protocol like http:// or git://).

+

What fetch doesn't do

+

git fetch, however, does not change anything about your local state. It will not update your main branch or change anything about how your file system looks right now.

+

This is important to understand because a lot of developers think that running git fetch will make their local work reflect the state of the remote. It may download all the necessary data to do that, but it does not actually change any of your local files. We will learn commands in later lessons to do just that :D

+

So at the end of the day, you can think of running git fetch as a download step.

+

To finish the level, simply git fetch and download all the commits!

+

Level: Git Pullin'

Git Pull

+

Now that we've seen how to fetch data from a remote repository with git fetch, let's update our work to reflect those changes!

+

There are actually many ways to do this -- once you have new commits available locally, you can incorporate them as if they were just normal commits on other branches. This means you could execute commands like:

+ +

In fact, the workflow of fetching remote changes and then merging them is so common that git actually provides a command that does both at once! That command is git pull.

+

Let's first see a fetch and a merge executed sequentially.

+
git fetch; git merge o/main

Boom -- we downloaded C3 with a fetch and then merged in that work with git merge o/main. Now our main branch reflects the new work from the remote (in this case, named origin)

+

What would happen if we used git pull instead?

+
git pull

The same thing! That should make it very clear that git pull is essentially shorthand for a git fetch followed by a merge of whatever branch was just fetched.

+

We will explore the details of git pull later (including options and arguments), but for now let's try it out in the level.

+

Remember -- you can actually solve this level with just fetch and merge, but it will cost you an extra command :P

+

Level: Faking Teamwork

Simulating collaboration

+

So here is the tricky thing -- for some of these upcoming lessons, we need to teach you how to pull down changes that were introduced in the remote.

+

That means we need to essentially "pretend" that the remote was updated by one of your coworkers / friends / collaborators, sometimes on a specific branch or a certain number of commits.

+

In order to do this, we introduced the aptly-named command git fakeTeamwork! It's pretty self explanatory, let's see a demo...

+

The default behavior of fakeTeamwork is to simply plop down a commit on main.

+
git fakeTeamwork

There we go -- the remote was updated with a new commit, and we haven't downloaded that commit yet because we haven't run git fetch.

+

You can also specify the number of commits or the branch by appending them to the command.

+
git fakeTeamwork foo 3

With one command we simulated a teammate pushing three commits to the foo branch on our remote.

+

The upcoming levels are going to be pretty difficult, so we're asking more of you for this level.

+

Go ahead and make a remote (with git clone), fake some changes on that remote, commit yourself, and then pull down those changes. It's like a few lessons in one!

+

Level: Git Pushin'

Git Push

+

Ok, so I've fetched changes from remote and incorporated them into my work locally. That's great and all... but how do I share my awesome work with everyone else?

+

Well, the way to upload shared work is the opposite of downloading shared work. And what's the opposite of git pull? git push!

+

git push is responsible for uploading your changes to a specified remote and updating that remote to incorporate your new commits. Once git push completes, all your friends can then download your work from the remote.

+

You can think of git push as a command to "publish" your work. It has a bunch of subtleties that we will get into shortly, but let's start with baby steps...

+

note -- the behavior of git push with no arguments varies depending on one of git's settings called push.default. The default value for this setting depends on the version of git you're using, but we are going to use the upstream value in our lessons. This isn't a huge deal, but it's worth checking your settings before pushing in your own projects.

+

Here we have some changes that the remote does not have. Let's upload them!

+
git push

There we go -- the remote received commit C2, the branch main on the remote was updated to point at C2, and our own reflection of the remote (o/main) was updated as well. Everything is in sync!

+

To finish this level, simply share two new commits with the remote. Strap in though, because these lessons are about to get a lot harder!

+

Level: Diverged History

Diverged Work

+

So far we've seen how to pull down commits from others and how to push up our own changes. It seems pretty simple, so how can people get so confused?

+

The difficulty comes in when the history of the repository diverges. Before discussing the details of this, let's see an example...

+

Imagine you clone a repository on Monday and start dabbling on a side feature. By Friday you are ready to publish your feature -- but oh no! Your coworkers have written a bunch of code during the week that's made your feature out of date (and obsolete). They've also published these commits to the shared remote repository, so now your work is based on an old version of the project that's no longer relevant.

+

In this case, the command git push is ambiguous. If you run git push, should git change the remote repository back to what it was on Monday? Should it try to add your code in while not removing the new code? Or should it totally ignore your changes since they are totally out of date?

+

Because there is so much ambiguity in this situation (where history has diverged), git doesn't allow you to push your changes. It actually forces you to incorporate the latest state of the remote before being able to share your work.

+

So much talking! Let's see this situation in action.

+
git push

See? Nothing happened because the command fails. git push fails because your most recent commit C3 is based off of the remote at C1. The remote has since been updated to C2 though, so git rejects your push.

+

How do you resolve this situation? It's easy, all you need to do is base your work off of the most recent version of the remote branch.

+

There are a few ways to do this, but the most straightforward is to move your work via rebasing. Let's go ahead and see what that looks like.

+

Now if we rebase before pushing instead...

+
git fetch; git rebase o/main; git push

Boom! We updated our local representation of the remote with git fetch, rebased our work to reflect the new changes in the remote, and then pushed them with git push.

+

Are there other ways to update my work when the remote repository has been updated? Of course! Let's check out the same thing but with merge instead.

+

Although git merge doesn't move your work (and instead just creates a merge commit), it's a way to tell git that you have incorporated all the changes from the remote. This is because the remote branch is now an ancestor of your own branch, meaning your commit reflects all commits in the remote branch.

+

Lets see this demonstrated...

+

Now if we merge instead of rebasing...

+
git fetch; git merge o/main; git push

Boom! We updated our local representation of the remote with git fetch, merged the new work into our work (to reflect the new changes in the remote), and then pushed them with git push.

+

Awesome! Is there any way I can do this without typing so many commands?

+

Of course -- you already know git pull is just shorthand for a fetch and a merge. Conveniently enough, git pull --rebase is shorthand for a fetch and a rebase!

+

Let's see these shorthand commands at work.

+

First with --rebase...

+
git pull --rebase; git push

Same as before! Just a lot shorter.

+

And now with regular pull.

+
git pull; git push

Again, exact same as before!

+

This workflow of fetching, rebase/merging, and pushing is quite common. In future lessons we will examine more complicated versions of these workflows, but for now let's try this out.

+

In order to solve this level, take the following steps:

+ +

Level: Locked Main

Remote Rejected!

+

If you work on a large collaborative team it's likely that main is locked and requires some Pull Request process to merge changes. If you commit directly to main locally and try pushing you will be greeted with a message similar to this:

+
 ! [remote rejected] main -> main (TF402455: Pushes to this branch are not permitted; you must use a pull request to update this branch.)
+
+

Why was it rejected?

+

The remote rejected the push of commits directly to main because of the policy on main requiring pull requests to instead be used.

+

You meant to follow the process creating a branch then pushing that branch and doing a pull request, but you forgot and committed directly to main. Now you are stuck and cannot push your changes.

+

The solution

+

Create another branch called feature and push that to the remote. Also reset your main back to be in sync with the remote otherwise you may have issues next time you do a pull and someone else's commit conflicts with yours.

+ +

Level Sequence: To Origin And Beyond -- Advanced Git Remotes!

+
And you thought being a benevolent dictator would be fun...
+

Level: Push Main!

Merging feature branches

+

Now that you're comfortable with fetching, pulling, and pushing, let's put these skills to the test with a new workflow.

+

It's common for developers on big projects to do all their work on feature branches (off of main) and then integrate that work only once it's ready. This is similar to the previous lesson (where side branches get pushed to the remote), but here we introduce one more step.

+

Some developers only push and pull when on the main branch -- that way main always stays updated to what is on the remote (o/main).

+

So for this workflow we combine two things:

+ +

Let's see a refresher real quick of how to update main and push work.

+
git pull --rebase; git push

We executed two commands here that:

+ +

This level is pretty hefty -- here is the general outline to solve:

+ +

:O intense! good luck, completing this level is a big step.

+

Level: Merging with remotes

Why not merge?

+

In order to push new updates to the remote, all you need to do is incorporate the latest changes from the remote. That means you can either rebase or merge in the remote branch (e.g. o/main).

+

So if you can do either method, why have the lessons focused on rebasing so far? Why is there no love for merge when working with remotes?

+

There's a lot of debate about the tradeoffs between merging and rebasing in the development community. Here are the general pros / cons of rebasing:

+

Pros:

+ +

Cons:

+ +

For example, commit C1 can be rebased past C3. It then appears that the work for C1' came after C3 when in reality it was completed beforehand.

+

Some developers love to preserve history and thus prefer merging. Others (like myself) prefer having a clean commit tree and prefer rebasing. It all comes down to preferences :D

+

For this level, let's try to solve the previous level but with merging instead. It may get a bit hairy but it illustrates the point well.

+

Level: Remote Tracking

Remote-Tracking branches

+

One thing that might have seemed "magical" about the last few lessons is that git knew the main branch was related to o/main. Sure these branches have similar names and it might make logical sense to connect the main branch on the remote to the local main branch, but this connection is demonstrated clearly in two scenarios:

+ +

Remote tracking

+

Long story short, this connection between main and o/main is explained simply by the "remote tracking" property of branches. The main branch is set to track o/main -- this means there is an implied merge target and implied push destination for the main branch.

+

You may be wondering how this property got set on the main branch when you didn't run any commands to specify it. Well, when you clone a repository with git, this property is actually set for you automatically.

+

During a clone, git creates a remote branch for every branch on the remote (aka branches like o/main). It then creates a local branch that tracks the currently active branch on the remote, which is main in most cases.

+

Once git clone is complete, you only have one local branch (so you aren't overwhelmed) but you can see all the different branches on the remote (if you happen to be very curious). It's the best of both worlds!

+

This also explains why you may see the following command output when cloning:

+
local branch "main" set to track remote branch "o/main"
+
+

Can I specify this myself?

+

Yes you can! You can make any arbitrary branch track o/main, and if you do so, that branch will have the same implied push destination and merge target as main. This means you can run git push on a branch named totallyNotMain and have your work pushed to the main branch on the remote!

+

There are two ways to set this property. The first is to checkout a new branch by using a remote branch as the specified ref. Running

+

git checkout -b totallyNotMain o/main

+

Creates a new branch named totallyNotMain and sets it to track o/main.

+

Enough talking, let's see a demonstration! We will checkout a new branch named foo and set it to track main on the remote.

+
git checkout -b foo o/main; git pull

As you can see, we used the implied merge target of o/main to update the foo branch. Note how main doesn't get updated!!

+

This also applies for git push.

+
git checkout -b foo o/main; git commit; git push

Boom. We pushed our work to the main on the remote even though our branch was named something totally different.

+

Way #2

+

Another way to set remote tracking on a branch is to simply use the git branch -u option. Running

+

git branch -u o/main foo

+

will set the foo branch to track o/main. If foo is currently checked out you can even leave it off:

+

git branch -u o/main

+

Let's see this other way of specifying remote tracking real quick...

+
git branch -u o/main foo; git commit; git push

Same as before, just a more explicit command. Sweet!

+

Ok! For this level let's push work onto the main branch on remote while not checked out on main locally. You should instead create a branch named side which the goal diagram will show.

+

Level: Git push arguments

Push arguments

+

Great! Now that you know about remote tracking branches we can start to uncover some of the mystery behind how git push, fetch, and pull work. We're going to tackle one command at a time but the concepts between them are very similar.

+

First we'll look at git push. You learned in the remote tracking lesson that git figured out the remote and the branch to push to by looking at the properties of the currently checked out branch (the remote that it "tracks"). This is the behavior with no arguments specified, but git push can optionally take arguments in the form of:

+

git push <remote> <place>

+

What is a <place> parameter you say? We'll dive into the specifics soon, but first an example. Issuing the command:

+

git push origin main

+

translates to this in English:

+

Go to the branch named "main" in my repository, grab all the commits, and then go to the branch "main" on the remote named "origin". Place whatever commits are missing on that branch and then tell me when you're done.

+

By specifying main as the "place" argument, we told git where the commits will come from and where the commits will go. It's essentially the "place" or "location" to synchronize between the two repositories.

+

Keep in mind that since we told git everything it needs to know (by specifying both arguments), it totally ignores where we are checked out!

+

Let's see an example of specifying the arguments. Note the location where we are checked out in this example.

+
git checkout C0; git push origin main

There we go! main got updated on the remote since we specified those arguments.

+

What if we hadn't specified the arguments? What would happen?

+
git checkout C0; git push

The command fails (as you can see), since HEAD is not checked out on a remote-tracking branch.

+

Ok, for this level let's update both foo and main on the remote. The twist is that git checkout is disabled for this level!

+

Note: The remote branches are labeled with o/ prefixes because the full origin/ label does not fit in our UI. Don't worry +about this... simply use origin as the name of the remote like normal.

+

Level: Git push arguments -- Expanded!

<place> argument details

+

Remember from the previous lesson that when we specified main as the place argument for git push, we specified both the source of where the commits would come from and the destination of where the commits would go.

+

You might then be wondering -- what if we wanted the source and destination to be different? What if you wanted to push commits from the foo branch locally onto the bar branch on remote?

+

Well unfortunately that's impossible in git... just kidding! Of course it's possible :)... git has tons and tons of flexibility (almost too much).

+

Let's see how in the next slide...

+

In order to specify both the source and the destination of <place>, simply join the two together with a colon:

+

git push origin <source>:<destination>

+

This is commonly referred to as a colon refspec. Refspec is just a fancy name for a location that git can figure out (like the branch foo or even just HEAD~1).

+

Once you are specifying both the source and destination independently, you can get quite fancy and precise with remote commands. Let's see a demo!

+

Remember, source is any location that git will understand:

+
git push origin foo^:main

Woah! That's a pretty trippy command but it makes sense -- git resolved foo^ into a location, uploaded whatever commits that weren't present yet on the remote, and then updated destination.

+

What if the destination you want to push doesn't exist? No problem! Just give a branch name and git will create the branch on the remote for you.

+
git push origin main:newBranch

Sweet, that's pretty slick :D

+

For this level, try to get to the end goal state shown in the visualization, and remember the format of:

+

<source>:<destination>

+

Level: Fetch arguments

Git fetch arguments

+

So we've just learned all about git push arguments, this cool <place> parameter, and even colon refspecs (<source>:<destination>). Can we use all this knowledge for git fetch as well?

+

You betcha! The arguments for git fetch are actually very, very similar to those for git push. It's the same type of concepts but just applied in the opposite direction (since now you are downloading commits rather than uploading).

+

Let's go over the concepts one at a time...

+

The <place> parameter

+

If you specify a place with git fetch like in the following command:

+

git fetch origin foo

+

Git will go to the foo branch on the remote, grab all the commits that aren't present locally, and then plop them down onto the o/foo branch locally.

+

Let's see this in action (just as a refresher).

+

By specifying a place...

+
git fetch origin foo

We download only the commits from foo and place them on o/foo.

+

You might be wondering -- why did git plop those commits onto the o/foo remote branch rather than just plopping them onto my local foo branch? I thought the <place> parameter is a place that exists both locally and on the remote?

+

Well git makes a special exception in this case because you might have work on the foo branch that you don't want to mess up!! This ties into the earlier lesson on git fetch -- it doesn't update your local non-remote branches, it only downloads the commits (so you can inspect / merge them later).

+

"Well in that case, what happens if I explicitly define both the source and destination with <source>:<destination>?"

+

If you feel passionate enough to fetch commits directly onto a local branch, then yes you can specify that with a colon refspec. You can't fetch commits onto a branch that is checked out, but otherwise git will allow this.

+

Here is the only catch though -- <source> is now a place on the remote and <destination> is a local place to put those commits. It's the exact opposite of git push, and that makes sense since we are transferring data in the opposite direction!

+

That being said, developers rarely do this in practice. I'm introducing it mainly as a way to conceptualize how fetch and push are quite similar, just in opposite directions.

+

Let's see this craziness in action:

+
git fetch origin C2:bar

Wow! See, git resolved C2 as a place on the origin and then downloaded those commits to bar (which was a local branch).

+

What if the destination doesn't exist before I run the command? Let's see the last slide but without bar existing beforehand.

+
git fetch origin C2:bar

See, it's JUST like git push. Git made the destination locally before fetching, just like git will make the destination on remote before pushing (if it doesn't exist).

+

No args?

+

If git fetch receives no arguments, it just downloads all the commits from the remote onto all the remote branches...

+
git fetch

Pretty simple, but worth going over just once.

+

Ok, enough talking! To finish this level, fetch just the specified commits in the goal visualization. Get fancy with those commands!

+

You will have to specify the source and destination for both fetch commands. Pay attention to the goal visualization since the IDs may be switched around!

+

Level: Source of nothing

Oddities of <source>

+

Git abuses the <source> parameter in two weird ways. These two abuses come from the fact that you can technically specify "nothing" as a valid source for both git push and git fetch. The way you specify nothing is via an empty argument:

+ +

Let's see what these do...

+

What does pushing "nothing" to a remote branch do? It deletes it!

+
git push origin :foo

There, we successfully deleted the foo branch on remote by pushing the concept of "nothing" to it. That kinda makes sense...

+

Finally, fetching "nothing" to a place locally actually makes a new branch.

+
git fetch origin :bar

Very odd / bizarre, but whatever. That's git for you!

+

This is a quick level -- just delete one remote branch and create a new branch with git fetch to finish!

+

Level: Pull arguments

Git pull arguments

+

Now that you know pretty much everything there is to know about arguments for git fetch and git push, there's almost really nothing left to cover for git pull :)

+

That's because git pull at the end of the day is really just shorthand for a fetch followed by merging in whatever was just fetched. You can think of it as running git fetch with the same arguments specified and then merging in where those commits ended up.

+

This applies even when you use crazy-complicated arguments as well. Let's see some examples:

+

Here are some equivalent commands in git:

+

git pull origin foo is equal to:

+

git fetch origin foo; git merge o/foo

+

And...

+

git pull origin bar:bugFix is equal to:

+

git fetch origin bar:bugFix; git merge bugFix

+

See? git pull is really just shorthand for fetch + merge, and all git pull cares about is where the commits ended up (the destination argument that it figures out during fetch).

+

Lets see a demo:

+

If we specify the place to fetch, everything happens as before with fetch but we merge in whatever was just fetched.

+
git pull origin main

See! by specifying main we downloaded commits onto o/main just as normal. Then we merged o/main to our currently checked out location which is not the local branch main. For this reason it can actually make sense to run git pull multiple times (with the same args) from different locations in order to update multiple branches.

+

Does it work with source and destination too? You bet! Let's see that:

+
git pull origin main:foo

Wow, that's a TON in one command. We created a new branch locally named foo, downloaded commits from remote's main onto that branch foo, and then merged that branch into our currently checked out branch bar. It's over 9000!!!

+

Ok to finish up, attain the state of the goal visualization. You'll need to download some commits, make some new branches, and merge those branches into other branches, but it shouldn't take many commands :P

+ +

Level Sequence: Moving Work Around

+
"Git" comfortable with modifying the source tree :P
+

Level: Cherry-pick Intro

Moving Work Around

+

So far we've covered the basics of git -- committing, branching, and moving around in the source tree. Just these concepts are enough to leverage 90% of the power of git repositories and cover the main needs of developers.

+

That remaining 10%, however, can be quite useful during complex workflows (or when you've gotten yourself into a bind). The next concept we're going to cover is "moving work around" -- in other words, it's a way for developers to say "I want this work here and that work there" in precise, eloquent, flexible ways.

+

This may seem like a lot, but it's a simple concept.

+

Git Cherry-pick

+

The first command in this series is called git cherry-pick. It takes on the following form:

+ +

It's a very straightforward way of saying that you would like to copy a series of commits below your current location (HEAD). I personally love cherry-pick because there is very little magic involved and it's easy to understand.

+

Let's see a demo!

+

Here's a repository where we have some work in branch side that we want to copy to main. This could be accomplished through a rebase (which we have already learned), but let's see how cherry-pick performs.

+
git cherry-pick C2 C4

That's it! We wanted commits C2 and C4 and git plopped them down right below us. Simple as that!

+

To complete this level, simply copy some work from the three branches shown into main. You can see which commits we want by looking at the goal visualization.

+

Level: Interactive Rebase Intro

Git Interactive Rebase

+

Git cherry-pick is great when you know which commits you want (and you know their corresponding hashes) -- it's hard to beat the simplicity it provides.

+

But what about the situation where you don't know what commits you want? Thankfully git has you covered there as well! We can use interactive rebasing for this -- it's the best way to review a series of commits you're about to rebase.

+

Let's dive into the details...

+

All interactive rebase means Git is using the rebase command with the -i option.

+

If you include this option, git will open up a UI to show you which commits are about to be copied below the target of the rebase. It also shows their commit hashes and messages, which is great for getting a bearing on what's what.

+

For "real" git, the UI window means opening up a file in a text editor like vim. For our purposes, I've built a small dialog window that behaves the same way.

+

When the interactive rebase dialog opens, you have the ability to do two things in our educational application:

+ +

It is worth mentioning that in the real git interactive rebase you can do many more things like squashing (combining) commits, amending commit messages, and even editing the commits themselves. For our purposes though we will focus on these two operations above.

+

Great! Let's see an example.

+

When you hit the button, an interactive rebase window will appear. Reorder some commits around (or feel free to unpick some) and see the result!

+
git rebase -i HEAD~4 --aboveAll

Boom! Git copied down commits in the exact same way you specified through the UI.

+

To finish this level, do an interactive rebase and achieve the order shown in the goal visualization. Remember you can always undo or reset to fix mistakes :D

+ +

Level Sequence: A Mixed Bag

+
A mixed bag of Git techniques, tricks, and tips
+

Level: Grabbing Just 1 Commit

Locally stacked commits

+

Here's a development situation that often happens: I'm trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.

+

All of these debugging / print statements are in their own commits. Finally I track down the bug, fix it, and rejoice!

+

Only problem is that I now need to get my bugFix back into the main branch. If I simply fast-forwarded main, then main would get all my debug statements which is undesirable. There has to be another way...

+

We need to tell git to copy only one of the commits over. This is just like the levels earlier on moving work around -- we can use the same commands:

+ +

To achieve this goal.

+

This is a later level so we will leave it up to you to decide which command you want to use, but in order to complete the level, make sure main receives the commit that bugFix references.

+

Level: Juggling Commits

Juggling Commits

+

Here's another situation that happens quite commonly. You have some changes (newImage) and another set of changes (caption) that are related, so they are stacked on top of each other in your repository (aka one after another).

+

The tricky thing is that sometimes you need to make a small modification to an earlier commit. In this case, design wants us to change the dimensions of newImage slightly, even though that commit is way back in our history!!

+

We will overcome this difficulty by doing the following:

+ +

There are many ways to accomplish this overall goal (I see you eye-ing cherry-pick), and we will see more of them later, but for now let's focus on this technique. +Lastly, pay attention to the goal state here -- since we move the commits twice, they both get an apostrophe appended. One more apostrophe is added for the commit we amend, which gives us the final form of the tree

+

That being said, I can compare levels now based on structure and relative apostrophe differences. As long as your tree's main branch has the same structure and relative apostrophe differences, I'll give full credit.

+

Level: Juggling Commits #2

Juggling Commits #2

+

If you haven't completed Juggling Commits #1 (the previous level), please do so before continuing

+

As you saw in the last level, we used rebase -i to reorder the commits. Once the commit we wanted to change was on top, we could easily --amend it and re-order back to our preferred order.

+

The only issue here is that there is a lot of reordering going on, which can introduce rebase conflicts. Let's look at another method with git cherry-pick.

+

Remember that git cherry-pick will plop down a commit from anywhere in the tree onto HEAD (as long as that commit isn't an ancestor of HEAD).

+

Here's a small refresher demo:

+
git cherry-pick C2

Nice! Let's move on.

+

So in this level, let's accomplish the same objective of amending C2 once but avoid using rebase -i. I'll leave it up to you to figure it out! :D

+

Remember, the exact number of apostrophe's (') on the commit are not important, only the relative differences. For example, I will give credit to a tree that matches the goal tree but has one extra apostrophe everywhere.

+

Level: Git Tags

Git Tags

+

As you have learned from previous lessons, branches are easy to move around and often refer to different commits as work is completed on them. Branches are easily mutated, often temporary, and always changing.

+

If that's the case, you may be wondering if there's a way to permanently mark historical points in your project's history. For things like major releases and big merges, is there any way to mark these commits with something more permanent than a branch?

+

You bet there is! Git tags support this exact use case -- they (somewhat) permanently mark certain commits as "milestones" that you can then reference like a branch.

+

More importantly though, they never move as more commits are created. You can't "check out" a tag and then complete work on that tag -- tags exist as anchors in the commit tree that designate certain spots.

+

Let's see what tags look like in practice.

+

Let's try making a tag at C1 which is our version 1 prototype.

+
git tag v1 C1

There! Quite easy. We named the tag v1 and referenced the commit C1 explicitly. If you leave the commit off, git will just use whatever HEAD is at.

+

For this level just create the tags in the goal visualization and then check v1 out. Notice how you go into detached HEAD state -- this is because you can't commit directly onto the v1 tag.

+

In the next level we'll examine a more interesting use case for tags.

+

Level: Git Describe

Git Describe

+

Because tags serve as such great "anchors" in the codebase, git has a command to describe where you are relative to the closest "anchor" (aka tag). And that command is called git describe!

+

Git describe can help you get your bearings after you've moved many commits backwards or forwards in history; this can happen after you've completed a git bisect (a debugging search) or when sitting down at the computer of a coworker who just got back from vacation.

+

Git describe takes the form of:

+

git describe <ref>

+

Where <ref> is anything git can resolve into a commit. If you don't specify a ref, git just uses where you're checked out right now (HEAD).

+

The output of the command looks like:

+

<tag>_<numCommits>_g<hash>

+

Where tag is the closest ancestor tag in history, numCommits is how many commits away that tag is, and <hash> is the hash of the commit being described.

+

Let's look at a quick example. For this tree below:

+
git tag v2 C3

The command git describe main would output:

+

v1_2_gC2

+

Whereas git describe side would output:

+

v2_1_gC4

+

That's pretty much all there is to git describe! Try describing a few of the locations in this level to get a feel for the command.

+

Once you're ready, just go ahead and commit once to finish the level. We're giving you a freebie :P

+ +

Level Sequence: Advanced Topics

+
For the truly brave!
+

Level: Rebasing over 9000 times

Rebasing Multiple Branches

+

Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto main.

+

Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have C7' at the bottom, C6' above that, and so on, all in order.

+

If you mess up along the way, feel free to use reset to start over again. Be sure to check out our solution and see if you can do it in fewer commands!

+

Level: Multiple parents

Specifying Parents

+

Like the ~ modifier, the ^ modifier also accepts an optional number after it.

+

Rather than specifying the number of generations to go back (what ~ takes), the modifier on ^ specifies which parent reference to follow from a merge commit. Remember that merge commits have multiple parents, so the path to choose is ambiguous.

+

Git will normally follow the "first" parent upwards from a merge commit, but specifying a number with ^ changes this default behavior.

+

Enough talking, let's see it in action.

+

Here we have a merge commit. If we checkout main^ without the modifier, we will follow the first parent after the merge commit.

+

(In our visuals, the first parent is positioned directly above the merge commit.)

+
git checkout main^

Easy -- this is what we are all used to.

+

Now let's try specifying the second parent instead...

+
git checkout main^2

See? We followed the other parent upwards.

+

The ^ and ~ modifiers can make moving around a commit tree very powerful:

+
git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2

Lightning fast!

+

Even crazier, these modifiers can be chained together! Check this out:

+
git checkout HEAD~^2~2

The same movement as before, but all in one command.

+

Put it to practice

+

To complete this level, create a new branch at the specified destination.

+

Obviously it would be easy to specify the commit directly (with something like C6), but I challenge you to use the modifiers we talked about instead!

+

Level: Branch Spaghetti

Branch Spaghetti

+

WOAHHHhhh Nelly! We have quite the goal to reach in this level.

+

Here we have main that is a few commits ahead of branches one two and three. For whatever reason, we need to update these three other branches with modified versions of the last few commits on main.

+

Branch one needs a re-ordering of those commits and an exclusion/drop of C5. Branch two just needs a pure reordering of the commits, and three only needs one commit transferred!

+

We will let you figure out how to solve this one -- make sure to check out our solution afterwards with show solution.

+ +
\ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 217abcee..9c3b6022 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,6 +5,7 @@ var { } = require('fs'); var path = require('path'); +var { marked } = require('marked'); var glob = require('glob'); var _ = require('underscore'); @@ -136,6 +137,11 @@ var clean = function () { .pipe(gClean()); }; +var convertMarkdownStringsToHTML = function(markdowns) { + return marked(markdowns.join('\n')); +}; + + var jshint = function() { return src([ 'gulpfile.js', @@ -204,15 +210,17 @@ var generateLevelDocs = function(done) { log('Generating level documentation...'); // Get all level files - const levelFiles = glob.sync('src/levels/**/*.js'); + const allLevels= require('./src/levels/index'); + const cssContent = readFileSync('./generatedDocs/github-markdown.css'); let htmlContent = ` Learn Git Branching - Level Documentation + -

Learn Git Branching - Level Documentation

+
+

Learn Git Branching - All Levels Documentation

`; - levelFiles.forEach(file => { - const content = require('./' + file.replace('.js', '')); - const level = content.level; - - if (!level) return; // Skip if not a valid level file + Object.keys(allLevels.sequenceInfo).forEach(sequenceKey => { + log('Processing sequence: ', sequenceKey); + const sequenceInfo = allLevels.sequenceInfo[sequenceKey]; htmlContent += ` -
-

${level.name?.en_US || 'Unnamed Level'}

- -

Goal Tree:

-
${level.goalTreeString || 'No goal tree specified'}
- -

Solution:

-
${level.solutionCommand || 'No solution specified'}
- -

Hint:

-

${level.hint?.en_US || 'No hint available'}

-
+

Level Sequence: ${sequenceInfo.displayName.en_US}

+
${sequenceInfo.about.en_US}
`; + + const levels = allLevels.levelSequences[sequenceKey]; + for (const level of levels) { + htmlContent += `

Level: ${level.name.en_US}

`; + + const startDialog = level.startDialog.en_US; + for (const dialog of startDialog.childViews) { + const childViewType = dialog.type; + if (childViewType === 'ModalAlert') { + htmlContent += convertMarkdownStringsToHTML(dialog.options.markdowns); + } else if (childViewType === 'GitDemonstrationView') { + htmlContent += convertMarkdownStringsToHTML(dialog.options.beforeMarkdowns); + htmlContent += `
${dialog.options.command}
`; + htmlContent += convertMarkdownStringsToHTML(dialog.options.afterMarkdowns); + } else { + throw new Error(`Unknown child view type: ${childViewType}`); + } + } + } + }); htmlContent += ` +
`;