[{"data":1,"prerenderedAt":1023},["ShallowReactive",2],{"/en-us/blog/tags/git/":3,"navigation-de-de":19,"banner-de-de":440,"footer-de-de":453,"git-tag-page-de-de":662},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"content":8,"config":10,"_id":12,"_type":13,"title":14,"_source":15,"_file":16,"_stem":17,"_extension":18},"/en-us/blog/tags/git","tags",false,"",{"tag":9,"tagSlug":9},"git",{"template":11},"BlogTag","content:en-us:blog:tags:git.yml","yaml","Git","content","en-us/blog/tags/git.yml","en-us/blog/tags/git","yml",{"_path":20,"_dir":21,"_draft":6,"_partial":6,"_locale":7,"data":22,"_id":436,"_type":13,"title":437,"_source":15,"_file":438,"_stem":439,"_extension":18},"/shared/de-de/main-navigation","de-de",{"logo":23,"freeTrial":28,"sales":33,"login":38,"items":43,"search":377,"minimal":413,"duo":427},{"config":24},{"href":25,"dataGaName":26,"dataGaLocation":27},"/de-de/","gitlab logo","header",{"text":29,"config":30},"Kostenlose Testversion anfordern",{"href":31,"dataGaName":32,"dataGaLocation":27},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":34,"config":35},"Vertrieb kontaktieren",{"href":36,"dataGaName":37,"dataGaLocation":27},"/de-de/sales/","sales",{"text":39,"config":40},"Anmelden",{"href":41,"dataGaName":42,"dataGaLocation":27},"https://gitlab.com/users/sign_in/","sign in",[44,88,187,192,298,358],{"text":45,"config":46,"cards":48,"footer":71},"Plattform",{"dataNavLevelOne":47},"platform",[49,55,63],{"title":45,"description":50,"link":51},"Die umfassendste KI-basierte DevSecOps-Plattform",{"text":52,"config":53},"Erkunde unsere Plattform",{"href":54,"dataGaName":47,"dataGaLocation":27},"/de-de/platform/",{"title":56,"description":57,"link":58},"GitLab Duo (KI)","Entwickle Software schneller mit KI in jeder Phase der Entwicklung",{"text":59,"config":60},"Lerne GitLab Duo kennen",{"href":61,"dataGaName":62,"dataGaLocation":27},"/de-de/gitlab-duo/","gitlab duo ai",{"title":64,"description":65,"link":66},"Gründe, die für GitLab sprechen","10 Gründe, warum Unternehmen sich für GitLab entscheiden",{"text":67,"config":68},"Mehr erfahren",{"href":69,"dataGaName":70,"dataGaLocation":27},"/de-de/why-gitlab/","why gitlab",{"title":72,"items":73},"Erste Schritte mit",[74,79,84],{"text":75,"config":76},"Platform Engineering",{"href":77,"dataGaName":78,"dataGaLocation":27},"/de-de/solutions/platform-engineering/","platform engineering",{"text":80,"config":81},"Entwicklererfahrung",{"href":82,"dataGaName":83,"dataGaLocation":27},"/de-de/developer-experience/","Developer experience",{"text":85,"config":86},"MLOps",{"href":87,"dataGaName":85,"dataGaLocation":27},"/de-de/topics/devops/the-role-of-ai-in-devops/",{"text":89,"left":90,"config":91,"link":93,"lists":97,"footer":169},"Produkt",true,{"dataNavLevelOne":92},"solutions",{"text":94,"config":95},"Alle Lösungen anzeigen",{"href":96,"dataGaName":92,"dataGaLocation":27},"/de-de/solutions/",[98,124,147],{"title":99,"description":100,"link":101,"items":106},"Automatisierung","CI/CD und Automatisierung zur Beschleunigung der Bereitstellung",{"config":102},{"icon":103,"href":104,"dataGaName":105,"dataGaLocation":27},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[107,111,115,120],{"text":108,"config":109},"CI/CD",{"href":110,"dataGaLocation":27,"dataGaName":108},"/de-de/solutions/continuous-integration/",{"text":112,"config":113},"KI-unterstützte Entwicklung",{"href":61,"dataGaLocation":27,"dataGaName":114},"AI assisted development",{"text":116,"config":117},"Quellcodeverwaltung",{"href":118,"dataGaLocation":27,"dataGaName":119},"/de-de/solutions/source-code-management/","Source Code Management",{"text":121,"config":122},"Automatisierte Softwarebereitstellung",{"href":104,"dataGaLocation":27,"dataGaName":123},"Automated software delivery",{"title":125,"description":126,"link":127,"items":132},"Sicherheit","Entwickle schneller, ohne die Sicherheit zu gefährden",{"config":128},{"href":129,"dataGaName":130,"dataGaLocation":27,"icon":131},"/de-de/solutions/security-compliance/","security and compliance","ShieldCheckLight",[133,138,143],{"text":134,"config":135},"Application Security Testing",{"href":136,"dataGaName":137,"dataGaLocation":27},"/solutions/application-security-testing/","Application security testing",{"text":139,"config":140},"Schutz der Software-Lieferkette",{"href":141,"dataGaLocation":27,"dataGaName":142},"/de-de/solutions/supply-chain/","Software supply chain security",{"text":144,"config":145},"Software Compliance",{"href":146,"dataGaName":144,"dataGaLocation":27},"/solutions/software-compliance/",{"title":148,"link":149,"items":154},"Bewertung",{"config":150},{"icon":151,"href":152,"dataGaName":153,"dataGaLocation":27},"DigitalTransformation","/de-de/solutions/visibility-measurement/","visibility and measurement",[155,159,164],{"text":156,"config":157},"Sichtbarkeit und Bewertung",{"href":152,"dataGaLocation":27,"dataGaName":158},"Visibility and Measurement",{"text":160,"config":161},"Wertstrommanagement",{"href":162,"dataGaLocation":27,"dataGaName":163},"/de-de/solutions/value-stream-management/","Value Stream Management",{"text":165,"config":166},"Analysen und Einblicke",{"href":167,"dataGaLocation":27,"dataGaName":168},"/de-de/solutions/analytics-and-insights/","Analytics and insights",{"title":170,"items":171},"GitLab für",[172,177,182],{"text":173,"config":174},"Enterprise",{"href":175,"dataGaLocation":27,"dataGaName":176},"/de-de/enterprise/","enterprise",{"text":178,"config":179},"Kleinunternehmen",{"href":180,"dataGaLocation":27,"dataGaName":181},"/de-de/small-business/","small business",{"text":183,"config":184},"den öffentlichen Sektor",{"href":185,"dataGaLocation":27,"dataGaName":186},"/de-de/solutions/public-sector/","public sector",{"text":188,"config":189},"Preise",{"href":190,"dataGaName":191,"dataGaLocation":27,"dataNavLevelOne":191},"/de-de/pricing/","pricing",{"text":193,"config":194,"link":196,"lists":200,"feature":285},"Ressourcen",{"dataNavLevelOne":195},"resources",{"text":197,"config":198},"Alle Ressourcen anzeigen",{"href":199,"dataGaName":195,"dataGaLocation":27},"/de-de/resources/",[201,234,257],{"title":202,"items":203},"Erste Schritte",[204,209,214,219,224,229],{"text":205,"config":206},"Installieren",{"href":207,"dataGaName":208,"dataGaLocation":27},"/de-de/install/","install",{"text":210,"config":211},"Kurzanleitungen",{"href":212,"dataGaName":213,"dataGaLocation":27},"/de-de/get-started/","quick setup checklists",{"text":215,"config":216},"Lernen",{"href":217,"dataGaLocation":27,"dataGaName":218},"https://university.gitlab.com/","learn",{"text":220,"config":221},"Produktdokumentation",{"href":222,"dataGaName":223,"dataGaLocation":27},"https://docs.gitlab.com/","product documentation",{"text":225,"config":226},"Best-Practice-Videos",{"href":227,"dataGaName":228,"dataGaLocation":27},"/de-de/getting-started-videos/","best practice videos",{"text":230,"config":231},"Integrationen",{"href":232,"dataGaName":233,"dataGaLocation":27},"/de-de/integrations/","integrations",{"title":235,"items":236},"Entdecken",[237,242,247,252],{"text":238,"config":239},"Kundenerfolge",{"href":240,"dataGaName":241,"dataGaLocation":27},"/de-de/customers/","customer success stories",{"text":243,"config":244},"Blog",{"href":245,"dataGaName":246,"dataGaLocation":27},"/de-de/blog/","blog",{"text":248,"config":249},"Remote",{"href":250,"dataGaName":251,"dataGaLocation":27},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":253,"config":254},"TeamOps",{"href":255,"dataGaName":256,"dataGaLocation":27},"/de-de/teamops/","teamops",{"title":258,"items":259},"Vernetzen",[260,265,270,275,280],{"text":261,"config":262},"GitLab-Services",{"href":263,"dataGaName":264,"dataGaLocation":27},"/de-de/services/","services",{"text":266,"config":267},"Community",{"href":268,"dataGaName":269,"dataGaLocation":27},"/community/","community",{"text":271,"config":272},"Forum",{"href":273,"dataGaName":274,"dataGaLocation":27},"https://forum.gitlab.com/","forum",{"text":276,"config":277},"Veranstaltungen",{"href":278,"dataGaName":279,"dataGaLocation":27},"/events/","events",{"text":281,"config":282},"Partner",{"href":283,"dataGaName":284,"dataGaLocation":27},"/partners/","partners",{"backgroundColor":286,"textColor":287,"text":288,"image":289,"link":293},"#2f2a6b","#fff","Perspektiven für die Softwareentwicklung der Zukunft",{"altText":290,"config":291},"the source promo card",{"src":292},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":294,"config":295},"Lies die News",{"href":296,"dataGaName":297,"dataGaLocation":27},"/de-de/the-source/","the source",{"text":299,"config":300,"lists":302},"Unternehmen",{"dataNavLevelOne":301},"company",[303],{"items":304},[305,310,316,318,323,328,333,338,343,348,353],{"text":306,"config":307},"Über",{"href":308,"dataGaName":309,"dataGaLocation":27},"/de-de/company/","about",{"text":311,"config":312,"footerGa":315},"Karriere",{"href":313,"dataGaName":314,"dataGaLocation":27},"/jobs/","jobs",{"dataGaName":314},{"text":276,"config":317},{"href":278,"dataGaName":279,"dataGaLocation":27},{"text":319,"config":320},"Geschäftsführung",{"href":321,"dataGaName":322,"dataGaLocation":27},"/company/team/e-group/","leadership",{"text":324,"config":325},"Team",{"href":326,"dataGaName":327,"dataGaLocation":27},"/company/team/","team",{"text":329,"config":330},"Handbuch",{"href":331,"dataGaName":332,"dataGaLocation":27},"https://handbook.gitlab.com/","handbook",{"text":334,"config":335},"Investor Relations",{"href":336,"dataGaName":337,"dataGaLocation":27},"https://ir.gitlab.com/","investor relations",{"text":339,"config":340},"Trust Center",{"href":341,"dataGaName":342,"dataGaLocation":27},"/de-de/security/","trust center",{"text":344,"config":345},"AI Transparency Center",{"href":346,"dataGaName":347,"dataGaLocation":27},"/de-de/ai-transparency-center/","ai transparency center",{"text":349,"config":350},"Newsletter",{"href":351,"dataGaName":352,"dataGaLocation":27},"/company/contact/","newsletter",{"text":354,"config":355},"Presse",{"href":356,"dataGaName":357,"dataGaLocation":27},"/press/","press",{"text":359,"config":360,"lists":361},"Kontakt",{"dataNavLevelOne":301},[362],{"items":363},[364,367,372],{"text":34,"config":365},{"href":36,"dataGaName":366,"dataGaLocation":27},"talk to sales",{"text":368,"config":369},"Support",{"href":370,"dataGaName":371,"dataGaLocation":27},"/support/","get help",{"text":373,"config":374},"Kundenportal",{"href":375,"dataGaName":376,"dataGaLocation":27},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":378,"login":379,"suggestions":386},"Schließen",{"text":380,"link":381},"Um Repositories und Projekte zu durchsuchen, melde dich an bei",{"text":382,"config":383},"gitlab.com",{"href":41,"dataGaName":384,"dataGaLocation":385},"search login","search",{"text":387,"default":388},"Vorschläge",[389,392,397,399,404,409],{"text":56,"config":390},{"href":61,"dataGaName":391,"dataGaLocation":385},"GitLab Duo (AI)",{"text":393,"config":394},"Code Suggestions (KI)",{"href":395,"dataGaName":396,"dataGaLocation":385},"/de-de/solutions/code-suggestions/","Code Suggestions (AI)",{"text":108,"config":398},{"href":110,"dataGaName":108,"dataGaLocation":385},{"text":400,"config":401},"GitLab auf AWS",{"href":402,"dataGaName":403,"dataGaLocation":385},"/de-de/partners/technology-partners/aws/","GitLab on AWS",{"text":405,"config":406},"GitLab auf Google Cloud",{"href":407,"dataGaName":408,"dataGaLocation":385},"/de-de/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":410,"config":411},"Warum GitLab?",{"href":69,"dataGaName":412,"dataGaLocation":385},"Why GitLab?",{"freeTrial":414,"mobileIcon":419,"desktopIcon":424},{"text":415,"config":416},"Kostenlos testen",{"href":417,"dataGaName":32,"dataGaLocation":418},"https://gitlab.com/-/trials/new/","nav",{"altText":420,"config":421},"GitLab-Symbol",{"src":422,"dataGaName":423,"dataGaLocation":418},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":420,"config":425},{"src":426,"dataGaName":423,"dataGaLocation":418},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"freeTrial":428,"mobileIcon":432,"desktopIcon":434},{"text":429,"config":430},"Erfahre mehr über GitLab Duo",{"href":61,"dataGaName":431,"dataGaLocation":418},"gitlab duo",{"altText":420,"config":433},{"src":422,"dataGaName":423,"dataGaLocation":418},{"altText":420,"config":435},{"src":426,"dataGaName":423,"dataGaLocation":418},"content:shared:de-de:main-navigation.yml","Main Navigation","shared/de-de/main-navigation.yml","shared/de-de/main-navigation",{"_path":441,"_dir":21,"_draft":6,"_partial":6,"_locale":7,"title":442,"button":443,"config":448,"_id":450,"_type":13,"_source":15,"_file":451,"_stem":452,"_extension":18},"/shared/de-de/banner","GitLab Duo Agent Platform ist jetzt in öffentlicher Beta!",{"text":444,"config":445},"Beta testen",{"href":446,"dataGaName":447,"dataGaLocation":27},"/de-de/gitlab-duo/agent-platform/","duo banner",{"layout":449},"release","content:shared:de-de:banner.yml","shared/de-de/banner.yml","shared/de-de/banner",{"_path":454,"_dir":21,"_draft":6,"_partial":6,"_locale":7,"data":455,"_id":658,"_type":13,"title":659,"_source":15,"_file":660,"_stem":661,"_extension":18},"/shared/de-de/main-footer",{"text":456,"source":457,"edit":463,"contribute":468,"config":473,"items":478,"minimal":650},"Git ist eine Marke von Software Freedom Conservancy und unsere Verwendung von „GitLab“ erfolgt unter Lizenz.",{"text":458,"config":459},"Quelltext der Seite anzeigen",{"href":460,"dataGaName":461,"dataGaLocation":462},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":464,"config":465},"Diese Seite bearbeiten",{"href":466,"dataGaName":467,"dataGaLocation":462},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":469,"config":470},"Beteilige dich",{"href":471,"dataGaName":472,"dataGaLocation":462},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":474,"facebook":475,"youtube":476,"linkedin":477},"https://x.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[479,502,557,586,620],{"title":45,"links":480,"subMenu":485},[481],{"text":482,"config":483},"DevSecOps-Plattform",{"href":54,"dataGaName":484,"dataGaLocation":462},"devsecops platform",[486],{"title":188,"links":487},[488,492,497],{"text":489,"config":490},"Tarife anzeigen",{"href":190,"dataGaName":491,"dataGaLocation":462},"view plans",{"text":493,"config":494},"Vorteile von Premium",{"href":495,"dataGaName":496,"dataGaLocation":462},"/de-de/pricing/premium/","why premium",{"text":498,"config":499},"Vorteile von Ultimate",{"href":500,"dataGaName":501,"dataGaLocation":462},"/de-de/pricing/ultimate/","why ultimate",{"title":503,"links":504},"Lösungen",[505,510,513,515,520,525,529,532,535,540,542,544,547,552],{"text":506,"config":507},"Digitale Transformation",{"href":508,"dataGaName":509,"dataGaLocation":462},"/de-de/topics/digital-transformation/","digital transformation",{"text":511,"config":512},"Sicherheit und Compliance",{"href":136,"dataGaName":137,"dataGaLocation":462},{"text":121,"config":514},{"href":104,"dataGaName":105,"dataGaLocation":462},{"text":516,"config":517},"Agile Entwicklung",{"href":518,"dataGaName":519,"dataGaLocation":462},"/de-de/solutions/agile-delivery/","agile delivery",{"text":521,"config":522},"Cloud-Transformation",{"href":523,"dataGaName":524,"dataGaLocation":462},"/de-de/topics/cloud-native/","cloud transformation",{"text":526,"config":527},"SCM",{"href":118,"dataGaName":528,"dataGaLocation":462},"source code management",{"text":108,"config":530},{"href":110,"dataGaName":531,"dataGaLocation":462},"continuous integration & delivery",{"text":160,"config":533},{"href":162,"dataGaName":534,"dataGaLocation":462},"value stream management",{"text":536,"config":537},"GitOps",{"href":538,"dataGaName":539,"dataGaLocation":462},"/de-de/solutions/gitops/","gitops",{"text":173,"config":541},{"href":175,"dataGaName":176,"dataGaLocation":462},{"text":178,"config":543},{"href":180,"dataGaName":181,"dataGaLocation":462},{"text":545,"config":546},"Öffentlicher Sektor",{"href":185,"dataGaName":186,"dataGaLocation":462},{"text":548,"config":549},"Bildungswesen",{"href":550,"dataGaName":551,"dataGaLocation":462},"/de-de/solutions/education/","education",{"text":553,"config":554},"Finanzdienstleistungen",{"href":555,"dataGaName":556,"dataGaLocation":462},"/de-de/solutions/finance/","financial services",{"title":193,"links":558},[559,561,563,565,568,570,572,574,576,578,580,582,584],{"text":205,"config":560},{"href":207,"dataGaName":208,"dataGaLocation":462},{"text":210,"config":562},{"href":212,"dataGaName":213,"dataGaLocation":462},{"text":215,"config":564},{"href":217,"dataGaName":218,"dataGaLocation":462},{"text":220,"config":566},{"href":222,"dataGaName":567,"dataGaLocation":462},"docs",{"text":243,"config":569},{"href":245,"dataGaName":246,"dataGaLocation":462},{"text":238,"config":571},{"href":240,"dataGaName":241,"dataGaLocation":462},{"text":248,"config":573},{"href":250,"dataGaName":251,"dataGaLocation":462},{"text":261,"config":575},{"href":263,"dataGaName":264,"dataGaLocation":462},{"text":253,"config":577},{"href":255,"dataGaName":256,"dataGaLocation":462},{"text":266,"config":579},{"href":268,"dataGaName":269,"dataGaLocation":462},{"text":271,"config":581},{"href":273,"dataGaName":274,"dataGaLocation":462},{"text":276,"config":583},{"href":278,"dataGaName":279,"dataGaLocation":462},{"text":281,"config":585},{"href":283,"dataGaName":284,"dataGaLocation":462},{"title":299,"links":587},[588,590,592,594,596,598,600,604,609,611,613,615],{"text":306,"config":589},{"href":308,"dataGaName":301,"dataGaLocation":462},{"text":311,"config":591},{"href":313,"dataGaName":314,"dataGaLocation":462},{"text":319,"config":593},{"href":321,"dataGaName":322,"dataGaLocation":462},{"text":324,"config":595},{"href":326,"dataGaName":327,"dataGaLocation":462},{"text":329,"config":597},{"href":331,"dataGaName":332,"dataGaLocation":462},{"text":334,"config":599},{"href":336,"dataGaName":337,"dataGaLocation":462},{"text":601,"config":602},"Sustainability",{"href":603,"dataGaName":601,"dataGaLocation":462},"/sustainability/",{"text":605,"config":606},"Vielfalt, Inklusion und Zugehörigkeit",{"href":607,"dataGaName":608,"dataGaLocation":462},"/de-de/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":339,"config":610},{"href":341,"dataGaName":342,"dataGaLocation":462},{"text":349,"config":612},{"href":351,"dataGaName":352,"dataGaLocation":462},{"text":354,"config":614},{"href":356,"dataGaName":357,"dataGaLocation":462},{"text":616,"config":617},"Transparenzerklärung zu moderner Sklaverei",{"href":618,"dataGaName":619,"dataGaLocation":462},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":621,"links":622},"Nimm Kontakt auf",[623,626,628,630,635,640,645],{"text":624,"config":625},"Sprich mit einem Experten/einer Expertin",{"href":36,"dataGaName":37,"dataGaLocation":462},{"text":368,"config":627},{"href":370,"dataGaName":371,"dataGaLocation":462},{"text":373,"config":629},{"href":375,"dataGaName":376,"dataGaLocation":462},{"text":631,"config":632},"Status",{"href":633,"dataGaName":634,"dataGaLocation":462},"https://status.gitlab.com/","status",{"text":636,"config":637},"Nutzungsbedingungen",{"href":638,"dataGaName":639,"dataGaLocation":462},"/terms/","terms of use",{"text":641,"config":642},"Datenschutzerklärung",{"href":643,"dataGaName":644,"dataGaLocation":462},"/de-de/privacy/","privacy statement",{"text":646,"config":647},"Cookie-Einstellungen",{"dataGaName":648,"dataGaLocation":462,"id":649,"isOneTrustButton":90},"cookie preferences","ot-sdk-btn",{"items":651},[652,654,656],{"text":636,"config":653},{"href":638,"dataGaName":639,"dataGaLocation":462},{"text":641,"config":655},{"href":643,"dataGaName":644,"dataGaLocation":462},{"text":646,"config":657},{"dataGaName":648,"dataGaLocation":462,"id":649,"isOneTrustButton":90},"content:shared:de-de:main-footer.yml","Main Footer","shared/de-de/main-footer.yml","shared/de-de/main-footer",{"allPosts":663,"featuredPost":1002,"totalPagesCount":1021,"initialPosts":1022},[664,690,714,737,757,779,801,821,844,866,885,903,922,941,961,981],{"_path":665,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":666,"content":674,"config":683,"_id":686,"_type":13,"title":687,"_source":15,"_file":688,"_stem":689,"_extension":18},"/de-de/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds",{"title":667,"description":668,"ogTitle":667,"ogDescription":668,"noIndex":6,"ogImage":669,"ogUrl":670,"ogSiteName":671,"ogType":672,"canonicalUrls":670,"schema":673},"Wir feiern das 20-jährige Git-Jubiläum mit dessen Erfinder Linus Torvalds","Erfahre, wie das Open-Source-Versionskontrollsystem entstanden ist und was Linus davon hält, neue Programmiersprachen zu Git hinzuzufügen.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662510/Blog/Hero%20Images/git-20-years-opt1.png","https://about.gitlab.com/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Wir feiern das 20-jährige Git-Jubiläum mit dessen Erfinder Linus Torvalds\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2025-04-07\",\n      }",{"title":667,"description":668,"authors":675,"heroImage":669,"date":677,"body":678,"category":679,"tags":680,"updatedDate":682},[676],"Patrick Steinhardt","2025-04-07","Das Versionskontrollsystem Git wurde am 7. April 2005 vom \"Vater\" des Linux-Kernels, Linus Torvalds, veröffentlicht. Heute feiern wir den 20. Jahrestag dieses wichtigen Projekts, das mittlerweile von fast allen Entwickler(inne)n verwendet wird. Zu diesem Anlass habe ich mit Linus über die Geschichte von Git und darüber gesprochen, warum er die Rolle des Chefentwicklers von Git abgegeben hat und was seiner Meinung nach die wichtigsten Meilensteine sind.\n\n**2005 warst du bereits Betreuer des aufstrebenden Linux-Kernels. Warum hast du dich entschieden, ein neues Versionskontrollsystem zu entwickeln?**\n\nAnfangs habe ich Versionskontrolle wirklich gehasst.\n\nIch habe herkömmliche Versionskontrollsysteme (CVS/RCS/SCCS) sowohl als Endbenutzer (z. B. beim Nachverfolgen von Open-Source-Projekten wie [GCC](https://gcc.gnu.org/)) als auch als Entwickler (bei Transmeta haben wir für alles CVS genutzt) kennengelernt und hatte wirklich eine tiefe Abneigung dagegen.\n\n\u003Cimg src=\"https://about.gitlab.com/images/blogimages/linustorvalds.png\" align=\"left\" width=\"200px\" style=\"padding-right: 20px; padding-bottom: 10px\"/>\n\nDamals wechselten die meisten Projekte, die CVS verwendeten, vermutlich zu [SVN](https://subversion.apache.org/), aber für mich war das ehrlich gesagt nur Schönrederei. SVN war ja nichts als CVS in einer anderen Form und mit einem geringfügig besseren UI, aber die grundlegenden Dinge waren nicht besser und es wurden sogar einige neue Probleme hinzugefügt.\n\nEs gibt zu viele Probleme mit CVS und den anderen Lösungen, um sie hier alle aufzulisten. Glücklicherweise wurden sie alle zum Großteil obsolet und junge Entwickler(innen) müssen sich wahrscheinlich nie mit einem dieser Systeme beschäftigen. Ich weigerte mich also kategorisch, für den Kernel damit zu arbeiten, auch wenn wir für die Nachverfolgung des Codes einiger Untersysteme (vor allem beim Netzwerk) in den 90ern tatsächlich CVS verwendeten.\n\nDamals lebte ich in der Bay Area. Larry McVoy, den ich von früheren Projekten kannte (vor allem von [Imbench](https://www.usenix.org/legacy/publications/library/proceedings/sd96/full_papers/mcvoy.pdf)), hatte BitMover gegründet, bei dem ein neues Versionskontrollmodell namens BitKeeper, oder kurz BK, verwendet wurde.\n\nBK war zwar nicht Open Source, aber Larry hatte eine Vorliebe für Open-Source-Projekte und hatte das Gefühl, dass die fehlende Versionskontrolle die Entwicklung des Kernels wirklich ausbremste. Er hatte nicht unrecht, aber die traditionelle Quellcodeverwaltung funktionierte für mich einfach nicht. Larry verbrachte einige Zeit damit, mir und David Miller (einem Netzwerkbetreuer und bestehendem CVS-Benutzer) zu zeigen, was BitKeeper alles konnte.\n\nBK war nicht perfekt und basierte wie so viele andere Systeme zur Quellcodeverwaltung auf dem Source Code Control System (SCCS) und setzte daher wie alle anderen auf dasselbe unzureichende Modell mit „dateibasiertem Verlauf“. Dieses verursachte riesige, fundamentale Probleme, wenn Dateien umbenannt und gelöscht wurden.\n\nAndererseits war BK nicht nur reine Schönrederei. Es basierte zwar grundlegend auf SCCS, aber auf höherer Ebene behob es einige wirklich fundamentale Probleme und ermöglichte eine echte verteilte Entwicklung. Zudem hatte es einen echten globalen – keinen reinen dateibasierten – Verlauf, sodass es tatsächlich Code von verschiedenen Entwicklungszweigen zusammenführen konnte.\n\nMit CVS war das Erstellen von Branches und deren Zusammenführung etwas, das man mit anderen planen und besprechen musste – also ein großes Ereignis. Mit BK war jedes Repository ein Branch. Heute halten wir das für selbstverständlich, und natürlich ist Git noch viel weiter gegangen: Es gibt viele Branches *pro* Repository. Doch auch das viel eingeschränktere Modell von BK war zu diesem Zeitpunkt ein echter Wendepunkt.\n\nAber wie gesagt, BK war nicht perfekt. Es nutzte einen dateibasierten Verlauf, was ein fundamentales Problem ist, denn dadurch können Dateien einfach nicht zuverlässig umbenannt und zusammengeführt werden, was unvermeidlich zu Chaos und Probleme führt (alle, die CVS kennen: Denkt an Attic …). Außerdem gab es Einschränkungen bei der Skalierbarkeit. Diese wurden aber nur langsam etwas problematischer.\n\nDas größte Problem bei BK war die Lizenzierung. Auch wenn im Laufe der Jahre (wir verwendeten BK von 2002 bis 2005) viele Kernel-Betreuer(innen) zu diesem System wechselten, gab es immer wieder Schwierigkeiten damit. Diese Schwierigkeiten spitzten sich Ende 2004 zu, als der Einsatz von BK für den Kernel einige Monate später praktisch nicht mehr möglich war.\n\nIch war nun in der Situation, dass ich drei Jahre lang endlich eine Versionskontrolle verwendet hatte, die tatsächlich funktionierte und viele Probleme gelöst hat. Ich wollte also keinesfalls wieder zum Zustand vor der Versionskontrolle zurückkehren, doch in den Jahren, in denen wir BK eingesetzt hatten, war von der Open-Source-Community nicht wirklich eine bessere Lösung gekommen.\n\nSicher, die Leute wussten, dass CVS und SVN nicht wirklich gut funktionierten, und es gab Projekte, in denen alternative Ansätze verfolgt wurden, doch diese waren teilweise sogar noch schlechter (sie waren im Grunde einfach nur schick verpacktes Patch-Tracking). Einige dagegen hatten zwar gute Ideen, machten aber schreckliche Entwicklungsfehler (siehe [Monotone](https://www.monotone.ca/)).\n\nIch sah mich also eine Weile um und erkannte dann, dass es nur einen Ausweg gab: Ich musste meine eigene Lösung programmieren.\n\nTechnisch gesehen dauerte es nur wenige Tage, die erste Version von Git zu erstellen – das kann man alles im Git-Commit-Verlauf nachlesen. Dort sieht man wunderbar, wie es von quasi Null zu einer gerade so nutzbaren Lösung wurde, für die ich dann eine Woche später Patches veröffentlichte (und die dann einige Tage danach aktiv für den Kernel verwendet wurde).\n\nDabei wird aber die Tatsache außer Acht gelassen, dass ich bis zu diesem Zeitpunkt schon eine Weile über das Problem *nachgedacht* hatte. Programmieren ist einfach. Ein gutes Konzept ist das, was zählt. Hinter diesen wenigen Tagen steckt also einiges an Vorarbeit, die sehr wichtig ist – und das sieht man im Verlauf nicht.\n\nDiese erste Version war sehr, sehr einfach und konnte vieles von dem nicht, was später noch kommen sollte. Man kann aber auch in diesen ersten Tagen schon viel vom Kernkonzept sehen.\n\n**Kannst du uns einen kurzen Rückblick über die ersten Tage und Wochen des Git-Projekts geben?**\n\nIch hatte im Grunde beschlossen, die Kernel-Entwicklung einzustellen, bis ich eine Alternative hatte, die für mich funktionierte. Das Resultat sollte eine verteilte Entwicklung und Höchstleistung ermöglichen sowie ein System sein, mit dem man absolut verlässlich jegliche Beeinträchtigung verhindern kann.\n\nIch möchte betonen, dass ich mich nicht wirklich für Quellcodeverwaltungssysteme interessierte. Ich war am Endergebnis interessiert, nicht am Prozess. Git war mir also nie so wichtig wie der Kernel: Ich arbeite an Linux, weil ich Kernels spannend finde. Ich habe an Git gearbeitet, weil ich es musste.\n\nDamit wären wir dann auch schon bei deiner nächsten Frage.\n\n**Du hast die Rolle des Chefentwicklers von Git nach einigen Monaten an Junio Hamano übergeben, der dies noch immer ist. Warum hast du deine Position abgegeben, und warum an Junio?**\n\nDie Übergabe der Rolle war keine schwierige Entscheidung. Es war vielmehr so: „Sobald ich jemanden finde, dem ich das Projekt anvertrauen kann, gehe ich wieder zurück und arbeite nur noch am Kernel.“\n\nDas soll nicht heißen, dass ich einfach alles hingeworfen und auf das Beste gehofft habe. Ich war rund vier Monate lang Chefentwickler von Git, weil ich spürte, dass ich jemanden finden musste, der gekommen war, um zu bleiben, und der diesen ominösen „guten Riecher“ hatte.\n\nJunio war als einer der Ersten dabei – quasi ab der ersten Woche. Aber ich bin nicht einfach zu ihm hin gerannt und habe gesagt: „Du bist dran.“ Es braucht eine Weile, bis man sieht, wer wirklich dabei bleibt und wer sinnvollen Code schreibt und sinnvolle Entscheidungen trifft.\n\nUnd ich denke, Junio war ein echtes Vorbild. Ich bekomme viel zu viel Lob für die paar Monate, die ich in Git gesteckt habe – besonders angesichts des 20-jährigen Jubiläums. Ich bin zwar dafür verantwortlich, dass das Kernkonzept richtig umgesetzt und das Projekt zum Laufen gebracht wurde, aber Junio hat das Projekt wirklich geleitet (damit will ich nicht die hunderten anderen Beteiligten vergessen).\n\n**Die erste Version des Versionskontrollsystems Mercurial wurde 12 Tage nach der ersten Version von Git am 19. April 2005 veröffentlicht. Viele Leute behaupten, dass die User Experience von Mercurial der von Git überlegen war, aber heute ist Git deutlich beliebter. Warum glaubst du, hat Git sich gegen Mercurial durchgesetzt?**\n\nOh, ein großer Teil davon sind offensichtlich nur Netzwerkeffekte, und Quellcodeverwaltungssysteme haben sehr starke Netzwerkeffekte. Deshalb hat CVS trotz all seiner Einschränkungen so lange überlebt.\n\nDer Kernel verwendete Git und es wurde irgendwann in der Community von Ruby on Rails sehr beliebt – und dann setzte es sich überall durch.\n\nAber ich bin wirklich überzeugt, dass das Konzept von Git besser ist. Das Kernmodell ist sowohl sehr einfach als auch sehr leistungsfähig, und ich denke, das machte es einfacher, es in andere Umgebungen zu übertragen. JGit war ein frühes Beispiel dafür, aber es gibt natürlich Implementierungen wie das virtuelle Dateisystem MSgit usw.\n\nWährend Git anfangs berühmt-berüchtigterweise schwierig zu nutzen war, glaube ich, dass vieles davon darauf zurückzuführen ist, dass die Leute Dinge zuvor „richtig“ machen mussten. Die Leute kamen nämlich von anderen Umgebungen und fanden Git nicht intuitiv, da Git ein paar harte Entscheidungen getroffen hatte, die Nutzer(innen) von herkömmlichen Quellcodeverwaltungssystemen niemals gemacht hätten.\n\n**Das Git-Projekt ist nie stehengeblieben, seit du die Rolle des Chefentwicklers an Junio übergeben hast, und die Community arbeitet kontinuierlich an neuen Funktionen. Was waren deiner Meinung nach die wichtigsten Meilensteine, nachdem du das Projekt verlassen hast?**\n\nDas ist schwer zu beantworten, da ich Git ja so entwickelt hatte, dass es für mich funktionierte. Die Dinge, die *ich* verwende, haben also quasi vom ersten Tag an funktioniert. Ein offensichtliches Beispiel: Für viele Leute war es offensichtlich ein riesiger Schritt, Git auf Windows zum Laufen zu bringen, aber *mich* betraf das überhaupt nicht. ;-)\n\nGit hat ja auch eine ganze Infrastruktur, mit der es einfacher zu nutzen ist. Die größten Meilensteine entstanden meiner Meinung nach aber, als die Menschen die Git-Infrastruktur heranzogen und Dinge darauf aufbauend entwickelten. Diese fließen natürlich oft auch wieder in Git-Funktionen ein, aber gleichzeitig ist der Meilenstein etwas Externes.\n\nEin offensichtliches Beispiel: Alle großen Git-Hosting-Websites waren große Meilensteine. Dadurch, dass Git verteilt war, waren diese viel einfacher zu entwickeln, aber der *Meilenstein* war dann, dass das Hosting es den Benutzer(innen) so einfach machte, Git für verschiedenste Projekte zu nutzen.\n\n**Wenn du wieder in der Lage wärst, hauptberuflich an Git zu arbeiten, gäbe es etwas, das du gerne implementieren würdest?**\n\nAuf keinen Fall. Git hat von Anfang an alles getan, was ich brauchte – ich nutze es tatsächlich nur ziemlich eingeschränkt, und mir ist nur ein Projekt wichtig.\n\nUnd ich sage „Auf keinen Fall“, weil ich mich auf eine meiner früheren Antworten beziehe: Ich war noch nie wirklich an Quellcodeverwaltungssystemen interessiert. Ich denke, ein wichtiger Grund dafür, dass Git sich von anderen Quellcodeverwaltungssystemen so sehr unterscheidet – größtenteils im positiven Sinne – ist, dass ich Git eher wie ein verteiltes Journaling-Dateisystem angegangen bin und nicht wie eine herkömmliche Quellcodeverwaltung.\n\n**Gibt es eine Funktion oder eine konzeptionelle Entscheidung in Git, die du im Nachhinein bereust?**\n\nKonzeptionelle Entscheidungen? Nein. Ich bin immer noch überzeugt, dass das übergeordnete Konzept sehr gut ist. Man kann verschiedene Git-Konzepte diskutieren, ohne auf die kleinteilige Komplexität der eigentlichen Implementierung eingehen zu müssen.\n\nUnd ich denke, das ist wichtig in einem Projekt. Man benötigt ein bestimmtes übergeordnetes Prinzip, dem die konzeptionelle Ausrichtung eines Projekts folgt.\n\nManchmal treiben die Leute das zu weit und denken, dass das übergeordnete Konzept bedeutet, dass die Implementierung dann sklavisch einem Kernprinzip folgen muss. Das ist aber auch falsch – die *Implementierung* hat viele hässliche Grenzfälle, da die Realität nun einmal hart ist und Menschen seltsame Dinge wollen. Es ist schon eine Art übergeordnetes Konzept nötig, auf das man sich beziehen kann und über das man auf übergeordneter Ebene argumentieren kann, bevor man sich die Hände an der harten Realität schmutzig macht.\n\nIch denke, Git hat da ein gutes Gleichgewicht gefunden. Ein sehr geradliniges Objektspeicher-Konzept („strukturierte Merkle-Bäume“, wenn du aus dem CS-Bereich kommst, oder stell sie dir einfach als „inhaltsadressierbaren Speicher“ vor, wenn du aus dem Dateisystem-Bereich kommst). Dieses Kernkonzept ist da, ist aber gleichzeitig in der Realität nur ein winziger Teil des eigentlichen Codes. Der größte Teil des *Codes* betrifft all die Dinge, die man mit dem Kernkonzept machen kann. Diese grundlegende konzeptionelle Klarheit gibt dem Projekt trotzdem eine Art übergeordnete Struktur.\n\nEs ist die gleiche Art von übergeordneter Struktur, die Unix selbst hatte, von „alles ist eine Datei“ bis hin zur Prozessabwicklung. Es gibt zwar ein paar übergeordnete „Konzepte“, aber bei 99 % des Codes geht es ganz einfach darum, das, was man auf diesem Design aufgebaut ist, so zu gestalten, dass es uns in der realen Welt nutzt.\n\nIch habe zwei Mantras hinsichtlich der Technologie: „Wenn ich weiter geblickt habe, so deshalb, weil ich auf den Schultern von Riesen stehe“ (Newton) und „Genie ist 1 % Inspiration und 99 % Prozent Transpiration“ (Edison).\n\nAber da wir schon über die 99 % Transpiration sprechen: Obwohl ich mit dem Gesamtdesign sehr zufrieden bin, gibt es sicherlich verschiedene Details, die ich anders gemacht hätte, wenn ich Git heute entwickeln würde.\n\nEhrlich gesagt, sind sie aber nicht so wichtig. Viel wichtiger sind all die *guten* Details, die in den letzten zwei Jahrzehnten entwickelt wurden.\n\n**Im Linux-Kernel wurde Rust als Programmiersprache für einige der Subsysteme eingeführt. Glaubst du, dass es sinnvoll ist, solche neueren Programmiersprachen auch in Git zu verwenden?**\n\nIch vermute, dass es bei Git weniger Gründe gibt, Sprachen zu mischen, was immer etwas schwierig ist.\n\nIm Kernel ist das Endergebnis eine einzige Kernel-Binärdatei – auch wenn der Großteil davon dynamisch als Module geladen werden kann, sind sie immer noch effektiv in einer einzige Binärdatei verbunden.\n\nDas macht die Verwendung mehrerer Sprachen komplexer. Andererseits gibt es für den Kernel auch mehr Gründe, sich mit der Speichersicherheit und folglich mit neueren Sprachen zu befassen.\n\nWenn jemand Teile von Git in Rust oder einer anderen Programmiersprache schreiben möchte, ist es vermutlich viel sinnvoller, einfach eine separate Implementierung zu erstellen, anstatt zu versuchen, in einer Binärdatei mehrere Sprachen zu mischen.\n\nDie Kernideen von Git sind im Grunde so einfach, dass es vermutlich nicht allzu schwierig ist, einfach parallele Implementierungen des Kernel zu haben. Dann kann man bestimmte Problembereiche gezielt angehen, in denen unterschiedliche Sprachen sinnvoll sind.\n\nDas haben wir natürlich schon in Git gesehen: Genau das ist JGit. Hier wurde eine andere Programmiersprache verwendet, die sinnvoller für die webbasierte Umgebung war.\n\nIch weiß, dass es bereits Rust-Implementierungen einiger der Kernfunktionen von Git gibt. Hier ist die Situation vermutlich ähnlich: Sie werden in bestimmten Situationen sinnvoller sein als einfach alles in Rust umzuwandeln.\n\nAllen, die sich für die Implementierung mit Rust interessieren, empfehle ich, nach Bereichen Ausschau zu halten, in denen die Vorteile von Rust offensichtlicher sind. Ich glaube nicht, dass die Verwendung von C für den Standard-Quellcode von Git wirklich so problematisch ist.\n\n**Alle paar Jahre tauchen neue Versionskontrollsysteme auf. Glaubst du, dass Git auch in Zukunft vorne dabei bleiben wird?**\n\nIch habe bereits die Netzwerkeffekte bei Quellcodeverwaltungssystemen erwähnt. Meiner Meinung nach muss ein neues System daher nicht einfach nur ein bisschen, sondern viel, viel besser sein, um Git zu ersetzen. Oder aber so kompatibel, dass es dann eigentlich nur eine neue Implementierung von Git ist.\n\nIch denke, dass sich die Situation in der Quellcodeverwaltung geändert hat: Git hat nicht die riesigen, fundamentalen Lücken, die Quellcodeverwaltungssysteme vor Git hatten. Es ist also ziemlich schwer, „enorm besser“ zu sein.\n\nAlso, ja, ich gehe davon aus, dass Git auf absehbare Zeit vorne dabei bleibt und die Leute eher an Verbesserungen *an* Git arbeiten als an Ersatzlösungen.\n\n*Hinweis: Dieses Interview wurde aus Platzgründen und zur besseren Übersichtlichkeit bearbeitet.* \n\n## Erfahre mehr über Git\n\n- [Was gibt es Neues in Git 2.49.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-49-0/)  \n- [Was gibt es Neues in Git 2.48.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-48-0/)\n- [Der Anfängerleitfaden zum „reftable“-Format von Git](https://about.gitlab.com/de-de/blog/a-beginners-guide-to-the-git-reftable-format/)\n- [Git-Projekt](https://git-scm.com/)","open-source",[681,9],"open source","2025-04-28",{"slug":684,"featured":90,"template":685},"celebrating-gits-20th-anniversary-with-creator-linus-torvalds","BlogPost","content:de-de:blog:celebrating-gits-20th-anniversary-with-creator-linus-torvalds.yml","Celebrating Gits 20th Anniversary With Creator Linus Torvalds","de-de/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds.yml","de-de/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds",{"_path":691,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":692,"content":699,"config":708,"_id":710,"_type":13,"title":711,"_source":15,"_file":712,"_stem":713,"_extension":18},"/de-de/blog/git-pull-vs-git-fetch-whats-the-difference",{"ogTitle":693,"schema":694,"ogImage":695,"ogDescription":696,"ogSiteName":697,"noIndex":6,"ogType":672,"ogUrl":698,"title":693,"canonicalUrls":698,"description":696},"Git Pull vs. Git Fetch: Unterschiede & Anwendung erklärt","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"git fetch vs. git pull: Das ist der Unterschied!\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-09-24\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660028/Blog/Hero%20Images/blog-image-template-1800x945__25_.png","Git Pull kombiniert fetch + merge in einem Befehl. Erfahre die Unterschiede zu Git Fetch, wann du welchen Command nutzt und vermeide typische Fehler.","https://about.gitlab.com/de-de","https://about.gitlab.com/de-de/blog/git-pull-vs-git-fetch-whats-the-difference",{"heroImage":695,"body":700,"authors":701,"updatedDate":703,"date":704,"title":705,"tags":706,"description":707,"category":679},"Der Git-Befehl ist als [verteiltes\nVersionskontrollsystem](https://about.gitlab.com/de-de/topics/version-control/benefits-distributed-version-control-system/)\nsehr beliebt und wird verwendet, wenn eine Synchronisation mit einem\nRemote-Repository erforderlich ist. \n\n\nEntwickler(innen) müssen die geeigneten Befehle basierend auf den Anforderungen des Projekts auswählen. In diesem Artikel erklären wir die Grundlagen und Unterschiede zwischen git fetch und git pull und geben eine detaillierte Erläuterung ihrer jeweiligen Anwendungsfälle.\n\n\n**In diesem Artikel lernst du:**\n\n\n* Wann du `git pull` vs. `git fetch` verwendest\n\n* Wie du Konflikte vermeidest (und löst, wenn sie auftreten)  \n\n* Welche Fallstricke es gibt und wie du sie umgehst\n\n\n## Inhaltsverzeichnis - git fetch vs. git pull: Das ist der Unterschied!\n\n\n* [Worum geht es bei git pull?](#worum-geht-es-bei-git-pull)\n\n* [Was ist git fetch?](#was-ist-git-fetch)\n\n* [git pull - Daten aktualisieren](#git-pull---daten-aktualisieren)\n\n* [git pull - Mehr als nur ein Befehl](#git-pull---mehr-als-nur-ein-befehl)\n\n* [git pull vs git fetch - Wann benutze ich welchen Befehl?](#git-pull-vs-git-fetch---wann-benutze-ich-welchen-befehl)\n\n* [git pull - Die Basis für kollaboratives Arbeiten](#git-pull---die-basis-für-kollaboratives-arbeiten)\n\n* [git fetch und git pull FAQs](#git-fetch-und-git-pull-faqs)\n\n  * [Wie oft sollte ich den Pull-Befehl ausführen?](#wie-oft-sollte-ich-den-pull-befehl-ausführen)\n  * [Was ist mit Autofetch oder Autopull?](#was-ist-mit-autofetch-oder-autopull)\n  * [Was passiert bei Problemen mit git pull?](#was-passiert-bei-problemen-mit-git-pull)\n  * [Ist git pull riskant?](#ist-git-pull-riskant)\n\n## Worum geht es bei git pull?\n\n\nGit pull nimmt eine essenzielle Rolle in der Versionskontrolle ein. Git ist ein Tool, das Entwicklerteams im Rahmen von DevSecOps dabei unterstützt, sowohl zeitgleich als auch zeitversetzt an einem Softwareprojekt zu arbeiten. Git sorgt unter anderem dafür, dass alle stets mit der aktuellen und korrekten Version arbeiten und jede Änderung für alle sichtbar ist. Dieser aktuelle Stand des Projekts wird in dem sogenannten zentralen Remote Repository festgehalten. \n\n\nEin Git-Repository ist deine Projektverwaltung. Es enthält nicht nur deine aktuellen Dateien, sondern die komplette Historie aller Änderungen. Stell es dir wie ein intelligentes Backup-System vor: Jeder 'Commit' ist ein Schnappschuss deines Projekts zu einem bestimmten Zeitpunkt. Das Repository speichert all diese Schnappschüsse effizient und ermöglicht dir, jederzeit zu früheren Versionen zurückzukehren.\n\n\nMitarbeiter(innen) können somit offline arbeiten und Änderungen in ihrem lokalen Repository und lokalen Arbeitsverzeichnis speichern. Sobald sie die Änderungen auf das Remote Repository übertragen, werden diese auch für alle anderen erkennbar.\n\n\nSo sorgt git für eine ständige Aktualisierung, sodass alle jederzeit mit den neuesten Daten arbeiten. Git pull ist der Schlüssel dazu, diese Versionskontrolle in die Praxis umzusetzen. \n\n\n## Was ist git fetch?\n\n\nDer Befehl git fetch ruft die neueste Commit-Historie aus dem Remote-Repository ab, beeinflusst aber nicht das lokale Arbeitsverzeichnis. Selbst nach dem Abrufen der Remote-Änderungen werden diese nicht im lokalen Branch übernommen. Er wird hauptsächlich verwendet, wenn Sie den neuesten Stand aus dem Remote-Repository abrufen und die Änderungen überprüfen möchten, bevor sie im lokalen Repository übernommen werden. Um die abgerufenen Änderungen auf den lokalen Branch anzuwenden, müssen Sie manuell git merge oder [git rebase](https://docs.gitlab.com/topics/git/git_rebase/) ausführen.\n\n\n## git pull - Daten aktualisieren\n\n\nWillst du dich als Entwickler(in) zu Beginn deiner Arbeit auf den neuesten Stand bringen? Dann wirst du wissen wollen, welche Änderungen seit deinem letzten Login vorgenommen wurden. \n\n\nDazu muss erwähnt werden, dass nicht alle Änderungen übernommen werden. Jedes Teammitglied nutzt den git-push-Befehl, um seine Änderungen ins Remote Repository hochzuladen. Diese landen meist in Feature-Branches. Teamleiter(innen) prüfen diese Änderungen und führen sie über Merge Requests in den Hauptbranch (main/master) zusammen. Mit git pull holst du dir dann die aktuellste Version dieses Hauptbranches auf deinen Rechner. \n\n\nDie einfachste Möglichkeit, die als „true” gekennzeichnete Version zu erhalten, besteht darin, diese Änderungen auf deinen Arbeitsplatz zu ziehen und dann auf dieser Basis weiterzuarbeiten. \n\nGenau diese Aufgabe übernimmt git pull. Es aktualisiert dein lokales Repository sowie deine projektbezogenen Dateien und sorgt somit dafür, dass du genau dort ansetzt, wo sich das Projekt gerade befindet. Das Fachmagazin Chip  bringt es auf den Punkt:\n\n„Den Pull-Befehl benötigen Sie im täglichen git-Workflow, um das lokale Repository mit den neuesten Änderungen zu aktualisieren.”\n\n\n## git pull - Mehr als nur ein Befehl\n\n\ngit pull ist mehr als nur ein Befehl. Und diese Aussage kannst du wörtlich nehmen. \n\nDenn obwohl du nur einen einzigen Command anwendest, passieren bei pull stets zwei Aktionen auf einmal. Es handelt sich hierbei um einen zusammengesetzten Befehl, der git fetch und git merge miteinander kombiniert und nacheinander ausführt:\n\n\ngit fetch zieht als erstes die aktuellen Daten aus dem Remote Repository in dein lokales Repository. Damit kannst du sehen, woran deine Kolleg(inn)en gearbeitet haben und welche Änderungen vorgenommen wurden. Noch aber werden diese Änderungen auf deinem Rechner nicht umgesetzt. \n\n\ngit merge übernimmt anschließend die Aktualisierung deines gesamten Projekts und bringt es auf den Stand des Remote Repository. Alles, was sich in deinem Arbeitsverzeichnis befindet, wird ebenfalls angepasst.\n\n\nFür viele git-Nutzer ist git pull eine tägliche Routine. Doch obwohl der Unterschied zwischen git fetch und git pull sehr fein ist, legen manche großen Wert darauf, die beiden Einzel-Commands fetch und merge stets getrennt zu nutzen. Warum eigentlich? Oder, um die Frage anders zu formulieren: \n\n\n## git pull vs git fetch - Wann benutze ich welchen Befehl?\n\n\nIn aller Regel wirst du als Entwickler(in) mit dem neuesten Stand des Projekts arbeiten wollen. Dazu müssen sowohl dein Repository als auch deine lokalen Daten in Einklang mit den als „true” gekennzeichneten Daten gebracht werden. Der Unterschied zwischen git fetch und git pull besteht darin, wie diese Aktualisierung erfolgt. \n\n\ngit pull ist die schnellste Methode, dieses Ziel umzusetzen. Hier ein praktisches Beispiel:\n\n\n```bash\n\n# Aktuelle Änderungen vom main-Branch holen und direkt anwenden\n\ngit pull origin main\n\n\n# Was im Hintergrund passiert:\n\ngit fetch origin main  # Änderungen herunterladen\n\ngit merge origin/main  # Änderungen in deinen Branch einarbeiten\n\n```\n\n\nMit diesem einen Befehl vermeidest du sowohl überflüssige Arbeitsschritte als auch Fehler, die daraus resultieren können, dass du mit einer nicht mehr aktuellen Version der Software arbeitest. Du arbeitest damit immer mit der neuesten Version und reduzierst das Risiko von Konflikten mit den Änderungen deiner Teamkollegen.\n\n\nZwar ist eine Fehlerkontrolle auch mit git pull noch möglich, doch jegliche Korrekturen inhaltlicher Natur können von dir nicht mehr hinterfragt werden.\n\nIndem du zuerst git fetch durchführst und erst später den merge (die “Verschmelzung”), kannst du noch weiterhin die Daten deines lokalen Working Directories nutzen und editieren. Erst nachdem du den git-merge-Befehl erteilst, vollziehst du die Umsetzung des neuen Stands. \n\n\n## git pull - Die Basis für kollaboratives Arbeiten\n\n\nDoch unabhängig davon, ob du git pull nutzt oder eine getrennte Ausführung von fetch und merge bevorzugst, bleibt die Bedeutung der damit verbundenen Aktionen unbestritten.\n\n\nGit pull ist die Basis für die zentrale Funktionalität von git: Ein fehlerfreies Arbeiten vieler Teammitglieder an einem geteilten Projekt, bei dem jede(r), unabhängig von Wohnsitz, Zeitzone und Rolle in dem Projekt stets an derselben Version des Produkts arbeitet. \n\n\nAlleine schon deswegen verdient der Command seine Einschätzung als einer der wichtigsten Befehle in git überhaupt. \n\n\n## git fetch und git pull FAQs\n\n\n### Wie oft sollte ich den Pull-Befehl ausführen?\n\n\nDies ist eine wichtige praktische Frage für viele Entwickler(innen). Allerdings gibt es keine Antwort, die Allgemeingültigkeit besitzt. Wenn du solo an einem Projekt arbeitest - beispielsweise alleine an einer lokalen Branch des Projekts - besteht keine Notwendigkeit, ständig einen pull durchzuführen. Du erfüllst schlicht deine Aufgabe und überträgst diese mit einem git-pull-Befehl ins Remote Repository. \n\n\nAnders sieht es aus, wenn du in einem kleinen Team am selben Teil (derselben lokalen Branch) des Produkts arbeitest. Hier kann es in der Praxis am einfachsten und effektivsten sein, wenn jede(r) die anderen kurz benachrichtigt, wenn eine Änderung durchgeführt wurde. Wenn alle Teammitglieder für sich einen pull durchführen, sind alle wieder auf dem neuesten Stand.\n\n\nIn größeren Teams ist diese Art der direkten Kommunikation nicht mehr effizient. Hier hängt eine Menge davon ab, wie schnell in der Regel Projekte umgesetzt oder Änderungen freigegeben werden. Je nachdem kann es sinnvoll sein, nur einmal oder mehrfach am Tag zu “pullen”. Eine andere logische Idee besteht darin, vor Beginn und nach Ende der eigenen Arbeit die Aktualisierung zu starten. \n\n\n### Was ist mit Autofetch oder Autopull?\n\n\nWenn eine der Kernfunktionen von git darin besteht, stets die aktuelle Version der Anwendung auf jedem Arbeitsplatz bereit zu stellen, wäre es dann nicht sinnvoll, wenn das System diese Updates regelmäßig selbst durchführt? Oder sogar immer dann, wenn eine neue Version als „true” gekennzeichnet wird? \n\n\nWir meinen, dass Autopull eher problematisch ist. Während du an deiner aktuellen Aufgabe arbeitest, kann es zu Konflikten mit den neuen Daten kommen. Es kann auch deinen Arbeitsfluss unterbrechen. Bei einem Autofetch wäre immerhin garantiert, dass nur das Repository angepasst wird und du noch immer Einsicht in die Änderungen hast, ehe sie auch lokal umgesetzt werden. Hier ist fraglich, ob es nicht trotzdem sinnvoll ist, den fetch nur durchzuführen, wenn du nicht an etwas anderem arbeitest und dich der Einsicht, beziehungsweise der Kontrolle widmen kannst. \n\nEs gibt durchaus Entwickler(innen), die ein automatisiertes pull oder fetch für sinnvoll halten und es gewinnbringend nutzen. Die meisten aber fühlen sich sicherer damit, die Befehle aktiv und bewusst zu verwenden.\n\n\n### Was passiert bei Problemen mit git pull?\n\n\nWie angedeutet, kann es zu Konflikten zwischen den Daten in dem Working Directory auf dem zentralen Server und deinem lokalen Directory kommen. In diesem Fall kann der pull-Befehl nicht ordnungsgemäß durchgeführt werden. Zum Glück ist das kein schwerwiegendes Problem. \n\n\nWas in diesem Fall passiert, ist schlicht, dass der pull-Command in einen fetch-Befehl umgewandelt wird. Das bedeutet, git gewährt dir Einblick in die Änderungen, die vorgenommen wurden und zeigt die Konflikte auf. Du kannst nun anschließend selbst die Fehler beseitigen (beziehungsweise Konflikte auflösen) und dann den merge umsetzen. \n\n\n### Ist git pull riskant?\n\n\nEs wird immer wieder von erfahrenen Entwickler(inne)n darauf hingewiesen, dass git pull nicht optimal ist. Aus ihrer Sicht gibt es eine Vielzahl universeller Schwierigkeiten mit diesem Command.\n\n\nEinige dieser Aspekte haben wir bereits aufgegriffen. Andere sind sehr spezifisch und beziehen sich darauf, wie pull die Repositories verändert. Eine gute Übersicht bietet diese Diskussion auf Stackoverflow (auf Englisch), die auf die Probleme detailliert eingeht. \n\n\nFür Anfänger(innen) ist es gewiss eine bessere Lernerfahrung, den Begriff in seine beiden Einzelkomponenten aufzuteilen, um genau zu erkennen, was genau sich durch die beiden Befehle, aus denen git pull eigentlich besteht, ändert. Profis andererseits mögen für ihre Bedürfnisse bessere Alternativen haben.\n\n\nAllgemein aber verwenden tausende Programmierer(innen) den pull-Command jeden Tag zu voller Zufriedenheit. Es gibt somit keinen Grund, ihn generell zu verteufeln oder von seiner Nutzung abzuraten.\n\n\n## Mehr erfahren\n\n\n* [Was ist neu in Git 2.46](https://about.gitlab.com/de-de/blog/what-s-new-in-git-2-50-0/)\n\n* [Git lernen](https://docs.gitlab.com/ee/topics/git/)\n\n* [Mehr über GitLab Gitaly erfahren](https://docs.gitlab.com/ee/administration/gitaly/)\n",[702],"GitLab","2025-07-28","2024-09-24","git pull vs. git fetch: Die Unterschiede erklärt",[9,681],"Ein Befehl, zwei Aktionen: Was git pull wirklich macht und wann git fetch die bessere Wahl ist.",{"slug":709,"featured":6,"template":685},"git-pull-vs-git-fetch-whats-the-difference","content:de-de:blog:git-pull-vs-git-fetch-whats-the-difference.yml","Git Pull Vs Git Fetch Whats The Difference","de-de/blog/git-pull-vs-git-fetch-whats-the-difference.yml","de-de/blog/git-pull-vs-git-fetch-whats-the-difference",{"_path":715,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":716,"content":722,"config":731,"_id":733,"_type":13,"title":734,"_source":15,"_file":735,"_stem":736,"_extension":18},"/de-de/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery",{"title":717,"description":718,"ogTitle":717,"ogDescription":718,"noIndex":6,"ogImage":719,"ogUrl":720,"ogSiteName":671,"ogType":672,"canonicalUrls":720,"schema":721},"OCI-Images als Quelle der Wahrheit für die kontinuierliche Lieferung","Die Vorteile der Verwendung von OCI-Images als Teil von GitOps-Workflows und die vielen Funktionen, die GitLab bietet, um die Bereitstellung in Kubernetes zu vereinfachen.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097601/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20Use%20this%20page%20as%20a%20reference%20for%20thumbnail%20sizes_76Tn5jFmEHY5LFj8RdDjNY_1750097600692.png","https://about.gitlab.com/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"OCI-Images als Quelle der Wahrheit für die kontinuierliche Lieferung\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Daniel Helfand\"}],\n        \"datePublished\": \"2025-02-19\",\n      }",{"title":717,"description":718,"authors":723,"heroImage":719,"date":725,"body":726,"category":679,"tags":727,"updatedDate":730},[724],"Daniel Helfand","2025-02-19","Ist [GitOps](https://about.gitlab.com/de-de/topics/gitops/) immer noch GitOps, wenn du kein Git-Repository als Artefakt für die Bereitstellung verwendest? Git bleibt zwar weiterhin von zentraler Bedeutung für GitOps-Workflows, doch die Speicherung von Infrastrukturdefinitionen als OCI-Artefakte (Open Container Initiative) in Container-Registries hat als Quelle für GitOps-Bereitstellungen an Beliebtheit gewonnen. In diesem Artikel werden wir uns eingehender mit den Ideen hinter diesem Trend befassen und erläutern, wie GitLab-Funktionen diese Verbesserung der GitOps-Workflows unterstützen.\n\n## Was ist GitOps?\n\nDas [OpenGitOps](https://opengitops.dev/)-Projekt hat [vier Prinzipien](https://opengitops.dev/#principles) für den Einsatz von GitOps definiert (Informationen zu OpenGitOps sind nur in englischer Sprache verfügbar):\n- Der gewünschte Zustand eines [Systems, das mit GitOps verwaltet wird](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#software-system), muss [deklarativ ausgedrückt](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#declarative-description) werden.\n- Der gewünschte Zustand wird so gespeichert, dass Unveränderlichkeit und Versionsverwaltung erzwungen werden und ein vollständiger Versionsverlauf erhalten bleibt.\n- Software-Agents rufen automatisch den gewünschten Zustand aus der Quelle ab.\n- Software-Agents überwachen [kontinuierlich](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#continuous) den tatsächlichen Systemzustand und [versuchen, den gewünschten Zustand anzuwenden](https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#reconciliation).\n\nEin Beispiel für GitOps ist das Speichern der Kubernetes-Manifeste für einen Microservice in einem GitLab-Projekt. Diese Kubernetes-Ressourcen werden dann kontinuierlich von einem [Controller](https://kubernetes.io/de/docs/concepts/architecture/controller/) abgeglichen, der auf dem Kubernetes-Cluster ausgeführt wird, auf dem der Microservice bereitgestellt ist. So können Entwickler(innen) die Infrastruktur mit denselben Workflows verwalten wie bei ihrer Arbeit mit regulärem Code, z. B. durch das Erstellen von Merge Requests, um Änderungen vorzunehmen und zu überprüfen, und durch die Versionsverwaltung von Änderungen. GitOps hat auch betriebliche Vorteile, wie z. B. die [Verhinderung von Konfigurationsdrift](https://about.gitlab.com/de-de/topics/gitops/#cicd) und es hilft Entwickler(inne)n bei der Prüfung, welche Änderungen bei der Bereitstellung zu bestimmten Ergebnissen geführt haben.\n\n## Vorteile und Einschränkungen von Git in GitOps-Workflows\n\nGit ist zwar ein wesentlicher Bestandteil von GitOps-Workflows, aber Git-Repositories wurden nicht für die Bereitstellung durch GitOps-Controller entwickelt. Entwickler(innen) können dank Git bei Infrastrukturänderungen zusammenarbeiten und diese Änderungen später überprüfen. Controller müssen jedoch nicht das gesamte Git-Repository herunterladen, um eine erfolgreiche Bereitstellung zu gewährleisten. GitOps-Controller benötigen lediglich die Infrastruktur, die für eine bestimmte Umgebung definiert ist. \n\nDarüber hinaus ist ein wichtiger Bestandteil des Bereitstellungsprozesses das [Signieren und Verifizieren von Bereitstellungen](https://docs.sigstore.dev/about/overview/#why-cryptographic-signing), um sicherzustellen, dass Bereitstellungsänderungen an einer Umgebung aus einer vertrauenswürdigen Quelle stammen. Git-Commits können zwar von GitOps-Controllern signiert und verifiziert werden, aber Commits können auch andere Details erfassen, die nicht mit der Bereitstellung selbst zusammenhängen (z. B. Dokumentationsänderungen, Aktualisierungen anderer Umgebungen und Umstrukturierungen des Git-Repositorys), oder nicht genug vom Bereitstellungsbild, da eine Bereitstellung aus mehreren Commits bestehen kann. Auch hier scheint es sich um einen Fall zu handeln, für den diese Git-Funktion nicht entwickelt wurde.  \n\nEin weiterer herausfordernder Aspekt von Git in GitOps-Workflows ist, dass es manchmal zu mehr Automatisierung als erwartet führen kann. Kurz nach der Zusammenführung wird eine Änderung am beobachteten Branch vorgenommen und dann bereitgestellt. Außerhalb von Git gibt es keine Kontrollen im Prozess. Wie kannst du sicherstellen, dass an einem Freitagnachmittag nichts bereitgestellt wird? Was ist, wenn die für die Bereitstellung verantwortlichen Teams nicht berechtigt sind, in bestimmten GitLab-Projekten Änderungen zusammenzuführen? Durch die Verwendung von OCI-Images wird eine Pipeline in den Prozess eingefügt, die alle Funktionen zur Bereitstellungsteuerung umfasst, wie z. B. [Approvals oder Bereitstellungsstopps (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n## OCI-Images\n\nDie [Open Container Initiative](https://opencontainers.org/) hat dazu beigetragen, Standards für Containerformate zu definieren. Während die meisten Entwickler(innen) mit dem Einbinden von Dockerfiles in Container-Images vertraut sind, sind viele möglicherweise nicht so erfahren im Speichern von Kubernetes-Manifesten in einer Container-Registry. Da die [Container-Registry von GitLab (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/user/packages/container_registry/) OCI-konform ist, können Benutzer(innen) Kubernetes-Manifeste für eine bestimmte Umgebung in eine Container-Registry übertragen. GitOps-Controller, wie z. B. [Flux CD (nur in englischer Sprache verfügbar)](https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/), können die in diesem OCI-Artefakt gespeicherten Manifeste verwenden, anstatt ein ganzes Git-Repository klonen zu müssen. \n\nIn GitOps-Workflows kann ein Git-Repository oft die Infrastrukturdefinitionen für alle Umgebungen enthalten, in denen ein Microservice bereitgestellt wird. Indem die Kubernetes-Manifeste nur für eine bestimmte Umgebung paketiert werden, muss Flux CD nur genau die Dateien herunterladen, die für die Bereitstellung in einer bestimmten Umgebung erforderlich sind. \n\n### Sicherheitsvorteile der Verwendung von OCI-Artefakten\n\nWie bereits erwähnt, bietet das Signieren und Verifizieren der Artefakte, die in einer Umgebung bereitgestellt werden sollen, eine zusätzliche Sicherheitsebene für Softwareprojekte. Nachdem Kubernetes-Manifeste an eine Container-Registry gepusht wurden, kann ein Tool wie [Sigstore Cosign](https://docs.sigstore.dev/quickstart/quickstart-cosign/) verwendet werden, um das OCI-Image mit einem privaten Schlüssel zu signieren, der sicher in einem GitLab-Projekt als [CI/CD-Variable (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/ci/variables/) gespeichert werden kann. Flux CD kann dann einen öffentlichen Schlüssel verwenden, der auf einem Kubernetes-Cluster gespeichert ist, um zu überprüfen, ob eine Bereitstellung von einer vertrauenswürdigen Quelle stammt. \n\n## Verwenden von GitLab zum Pushen und Signieren von OCI-Images \n\nGitLab bietet viele Funktionen, die den Prozess des Paketierens, Signierens und der Bereitstellung von OCI-Images vereinfachen. Eine gängige Methode zur Strukturierung von GitLab-Projekten mit GitOps-Workflows besteht darin, separate GitLab-Projekte für den Code der Microservices und ein einziges Infrastruktur-Repository für alle Microservices zu verwenden. Wenn eine Anwendung aus `n`-Microservices besteht, wären für eine Anwendung `n+1`-GitLab-Projekte erforderlich.\n\nDas Artefakt, das aus einem Programmierprojekt hervorgeht, ist in der Regel ein Container-Image, das zum Paketieren der Anwendung verwendet wird. Das Infrastruktur- oder Bereitstellungsprojekt enthält die Kubernetes-Manifeste, in denen alle Ressourcen definiert sind, die für die Skalierung und die Bereitstellung des Datenverkehrs für jeden Microservice erforderlich sind. Das Artefakt, das aus diesem Projekt hervorgeht, ist in der Regel ein OCI-Image, das zur Bereitstellung der Anwendung und anderer Manifeste für Kubernetes verwendet wird. \n\nIn diesem Setup wird die Trennung von Umgebungen durch die Definition von Kubernetes-Manifesten in separaten Ordnern gehandhabt. Diese Ordner stellen Umgebungen (z. B. Entwicklung, Staging und Produktion) dar, in denen die Anwendung gehostet wird. Wenn Änderungen am Codeprojekt vorgenommen und ein neues Container-Image gepusht wird, müssen zur Bereitstellung dieser Änderungen über die Integration von GitLab mit Flux CD lediglich die Manifeste im Ordner „Environment“ bearbeitet werden, um die neue Image-Referenz aufzunehmen, und ein „Merge Request“ geöffnet werden. Sobald dieser Merge Request überprüft, genehmigt und zusammengeführt wurde, wird der CI/CD-Job des Bereitstellungsprojekts ein neues OCI-Image pushen, das Flux CD aufnimmt und in der neuen Umgebung bereitstellt.\n\n![OCI-Images – Flowchart](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097611/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097611046.png)\n\nDas Signieren eines OCI-Image ist so einfach wie das Einfügen von Cosign in den CI/CD-Job deines Projekts. Du kannst einfach einen neuen öffentlichen und privaten Schlüssel mit Cosign generieren, indem du die folgenden Befehle lokal ausführst. Stelle einfach sicher, dass du dich mit der [glab-CLI](https://gitlab.com/gitlab-org/cli/#installation) bei deiner GitLab-Instanz anmeldest und die [`PROJECT_ID`] für den Befehl „cosign“ durch die [ID deines Bereitstellungsprojekts](https://docs.gitlab.com/ee/user/project/working_with_projects.html#access-a-project-by-using-the-project-id) ersetzt.   \n\n```\nglab auth login\ncosign generate-key-pair gitlab://[PROJECT_ID]\n```\n\nSobald der Befehl „cosign“ erfolgreich ausgeführt wurde, findest du die zu deinem Projekt hinzugefügten Cosign-Schlüssel im Abschnitt „CI/CD-Variablen“ unter den Schlüsselnamen `COSIGN_PUBLIC_KEY` und `COSIGN_PRIVATE_KEY`.\n\n### Beispiel für einen CI/CD-Job\n\nEin GitLab-CI/CD-Job zum Pushen eines OCI-Images sieht in etwa so aus:\n\n```yaml\nfrontend-deploy:\n  rules:\n  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    changes:\n      paths: \n      - manifests/dev/frontend-dev.yaml\n  trigger:\n    include:\n      - component: gitlab.com/components/fluxcd/oci-artifact@0.3.1\n        inputs:\n          version: 0.3.1\n          kubernetes_agent_reference: gitlab-da/projects/tanuki-bank/flux-config:dev\n          registry_image_url: \"oci://$CI_REGISTRY_IMAGE/frontend\"\n          image_tag: dev\n          manifest_path: ./manifests/dev/frontend-dev.yaml\n          flux_oci_repo_name: frontend\n          flux_oci_namespace_name: frontend-dev\n          signing_private_key: \"$COSIGN_PRIVATE_KEY\" \n```\n\nDer [GitLab-CI/CD-Katalog (nur in englischer Sprache verfügbar)](https://about.gitlab.com/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/) bietet eine von GitLab gepflegte [CI/CD-Komponente für die Arbeit mit OCI-Artefakten und Flux CD](https://gitlab.com/explore/catalog/components/fluxcd). Mit dieser Komponente können Entwicklungsteams Kubernetes-Manifeste als OCI-Images an die Container-Registry von GitLab oder eine externe Container-Registry senden, das OCI-Image mit Cosign signieren und das neu gepushte Image sofort über Flux CD abgleichen. \n\nIm obigen Beispiel ist die Flux CD `component` in einer `.gitlab-ci.yml`-Datei eines GitLab-Projekts enthalten. Mithilfe der `inputs` der Komponente können Benutzer(innen) definieren, in welche Registry das Image gepusht werden soll (d. h. `registry_image_url` und `image tag`), den Dateipfad zu den Kubernetes-Manifesten, die gepusht werden sollen (d. h. `manifest_path`), den privaten Cosign-Schlüssel, der zum Signieren von Images verwendet wird (d. h. `signing_private_key`), sowie den Kubernetes-Namensraum und den Namen des Flux-CD-[OCIRepository](https://fluxcd.io/flux/components/source/ocirepositories/), der für die Synchronisierung von Aktualisierungen in einer Umgebung benötigt wird (d. h. `flux_oci_namespace_name` und `flux_oci_repo_name`).\n\nMit der `kubernetes_agent_reference` können GitLab-CI/CD-Jobs das für den Zugriff auf einen Kubernetes-Cluster erforderliche `kubeconfig` erben, ohne dass in jedem GitLab-Projekt eine `kubeconfig`-CI/CD-Variable gespeichert werden muss. Durch die Einrichtung des [GitLab Agent for Kubernetes (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/user/clusters/agent/) können die CI/CD-Jobs aller GitLab-Projekte in einer [GitLab-Gruppe (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/user/group/) konfiguriert werden, um Berechtigungen für die Bereitstellung im Kubernetes-Cluster zu erben. \n\nDer Agent für den Kubernetes-Kontext wird normalerweise überall dort konfiguriert, wo du den GitLab Agent for Kubernetes in deiner GitLab-Gruppe konfigurierst. Das solltest du in der Regel in dem Projekt zu tun, in dem Flux CD verwaltet wird. Weitere Informationen zur Konfiguration des Agents für den CI/CD-Zugriff findest du in unserer [CI/CD-Workflow-Dokumentation (nur in englischer Sprache verfügbar)]( https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html).\n\nDie Variablen `$COSIGN_PRIVATE_KEY`, `$FLUX_OCI_REPO_NAME` und `$FRONTEND_DEV_NAMESPACE` sind Werte, die als CI/CD-Variablen gespeichert werden, um den Zugriff auf diese vertraulichen Daten in CI/CD-Protokollen zu erleichtern und sie zu maskieren. `$CI_REGISTRY_IMAGE` ist eine Variable, die standardmäßig in GitLab-Jobs verfügbar ist und die Container-Registry des GitLab-Projekts angibt. \n\n### Bereitstellen von OCI-Images\n\nWenn du [Flux CD mit deinen GitLab-Projekten (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/user/clusters/agent/gitops/flux_tutorial.html) verwendest, kannst du die Bereitstellung und Signaturprüfung für die Umgebungen deiner Microservices automatisieren. Sobald Flux CD für die Synchronisierung von einem GitLab-Projekt konfiguriert ist, kannst du die folgenden [benutzerdefinierten Ressourcendefinitionen](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) von Kubernetes zu deinem Projekt hinzufügen, um dein gepushtes OCI-Image zu synchronisieren. \n\n```yaml\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: frontend-dev\n  labels:\n    name: frontend-dev\n---\napiVersion: bitnami.com/v1alpha1\nkind: SealedSecret\nmetadata:\n  name: cosign-public-key\n  namespace: frontend-dev\nspec:\n  encryptedData:\n    cosign.pub: AgAKgLf4VbVzJOmr6++k81LlFayx88AELaUQFNOaXmBF4G+fBfBYeABl0skNvMAa1UrPVNSfMIHgFoYHoO96g576a+epk6V6glOI+++XvYbfsygof3GGxe0nL5Qh2b3ge0fNpyd0kTPSjTj0YUhRhKtMGMRSRw1jrwhNcGxCHK+Byibs52v8Np49KsIkeZKbzLdgYABkrv+k0j7hQM+jR180NpG+2UiRvaXpPuogxkbj61FEqWGrJHk8IVyfl3eh+YhoXxOHGDqko6SUC+bUZPDBlU6yKegO0/8Zq3hwulrSEsEjzRZNK+RFVMOLWWuC6h+WGpYhAMcsZPwjjJ/y29KLNa/YeqkN/cdk488QyEFc6ehCxzhH67HxIn2PDa+KkEOTv2TuycGF+Q00jKIizXF+IwLx/oRb3pTCF0AoAY8D8N3Ey+KfkOjsBON7gGID8GbQiJqX2IgIZxFMk0JRzxbRKOEqn+guLd5Shj7CD1a1Mkk0DxBdbqrGv2XNYUaFPI7xd3rZXUJZlnv+fsmwswsiGWRuXwim45HScWzQnfgLAe7tv3spVEGeaO5apl6d89uN21PBQnfE/zyugB//7ZW9tSp6+CSMyc5HynxI8diafqiwKPgvzLmVWRnkvxJijoXicRr3sCo5RudZPSlnjfd7CKdhwEVvLl7dRR4e/XBMdxCzk1p52Pl+3/kJR+LJii5+iwOpYrpVltSZdzc/3qRd19yMpc9PWpXYi7HxTb24EOQ25i21eDJY1ceplDN6bRtop2quzkjlwVeE2i4cEsX/YG8QBtQbop/3fjiAjKaED3QH3Ul0PECS9ARTScSkcOL3I00Xpp8DyD+xH0/i9wCBRDmH3yKX18C8VrMq02ALSnlP7WCVVjCPzubqKx2LPZRxK9EG0fylwv/vWQzTUUwfbPQZsd4c75bSTsTvxqp/UcFaXA==\n  template:\n    metadata:\n      name: cosign-public-key\n      namespace: frontend-dev\n---\napiVersion: source.toolkit.fluxcd.io/v1beta2\nkind: OCIRepository\nmetadata:\n    name: frontend\n    namespace: frontend-dev\nspec:\n    interval: 1m\n    url: oci://registry.gitlab.com/gitlab-da/projects/tanuki-bank/tanuki-bank-delivery/frontend\n    ref:\n        tag: dev\n    verify:\n      provider: cosign\n      secretRef:\n        name: cosign-public-key\n---\napiVersion: kustomize.toolkit.fluxcd.io/v1\nkind: Kustomization\nmetadata:\n    name: frontend\n    namespace: frontend-dev\nspec:\n    interval: 1m\n    targetNamespace: frontend-dev\n    path: \".\"\n    sourceRef:\n        kind: OCIRepository\n        name: frontend\n    prune: true\n``` \n\nMit der Ressource [`Kustomization`](https://fluxcd.io/flux/components/kustomize/kustomizations/) können Kubernetes-Manifeste weiter angepasst werden und sie gibt auch an, in welchem Namensraum Ressourcen bereitgestellt werden sollen. Die Ressource `OCIRepository` für Flux CD ermöglicht es Benutzer(inne)n, die OCI-Image-Repositoryreferenz und das Tag anzugeben, von dem regelmäßig synchronisiert werden soll. Außerdem wirst du die Eigenschaften `verify.provider` und `verify.secretRef` bemerken. Anhand dieser Felder kannst du überprüfen, ob das für den Cluster bereitgestellte OCI-Image mit dem entsprechenden privaten Cosign-Schlüssel signiert wurde, der im früheren CI/CD-Job verwendet wurde. \n\nDer öffentliche Schlüssel muss in einem [Kubernetes-Geheimnis](https://kubernetes.io/docs/concepts/configuration/secret/) gespeichert werden, das sich im selben Namensraum wie die Ressource `OCIRepository` befinden muss. Damit Flux CD dieses Geheimnis verwaltet und es nicht im Klartext gespeichert wird, kannst du [SealedSecrets](https://fluxcd.io/flux/guides/sealed-secrets/) verwenden, um den Wert zu verschlüsseln und ihn cluster-seitig von einem Controller entschlüsseln zu lassen. \n\nEine einfachere Methode, für die SealedSecrets nicht erforderlich ist, ist die [Bereitstellung des Geheimnisses über einen GitLab-CI/CD-Job (nur in englischer Sprache verfügbar)](https://docs.gitlab.com/ee/user/clusters/agent/getting_started_deployments.html) mit der [`kubectl CLI`](https://kubernetes.io/docs/reference/kubectl/). Bei der Variante ohne SealedSecret entfernst du einfach das oben enthaltene SealedSecret und führst den Job zur Bereitstellung des öffentlichen Geheimnis-Schlüssels aus, bevor du den Job zum Pushen des neuen OCI-Images ausführst. Dadurch wird sichergestellt, dass das Geheimnis sicher in GitLab gespeichert ist und dass es im Cluster vom OCIRepository abgerufen werden kann. Dieser Ansatz ist etwas einfacher, aber nicht für die Verwaltung von Geheimnissen in der Produktion geeignet. \n\n## Die Vorteile von OCI, GitLab und GitOps\n\nMit OCI-Artefakten (Oracle Cloud Infrastructure) können GitOps-Teams Bereitstellungen noch weiter optimieren. Sie bieten zusätzliche Sicherheitsvorteile und ermöglichen minimale Bereitstellungen. Benutzer(innen) profitieren weiterhin von allen Vorteilen, die Git bietet, insbesondere von einer zuverlässigen Datenquelle für die Infrastruktur und der Zusammenarbeit an Projekten. OCI-Images erweitern den Bereitstellungsansatz von GitOps um einen Paketierungsansatz.\n\nBei GitLab lernen wir kontinuierlich von unseren Kund(inn)en und der Cloud-nativen Community, um Erfahrungen zu sammeln, die zur Vereinfachung von GitOps-Workflows beitragen. Einige der in diesem Blogbeitrag erwähnten Funktionen kannst du nutzen, indem du dich für eine [kostenlose Testversion von GitLab Ultimate](https://about.gitlab.com/de-de/free-trial/) anmeldest. Wir freuen uns auch über Erfahrungsberichte von Benutzer(inne)n dieser Tools. Feedback kannst du im [Community-Forum](https://forum.gitlab.com/t/oci-images-as-source-of-truth-for-gitops-with-gitlab/120965) abgeben.\n",[108,681,728,536,9,729],"kubernetes","tutorial","2025-05-12",{"slug":732,"featured":6,"template":685},"how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery","content:de-de:blog:how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery.yml","How To Use Oci Images As The Source Of Truth For Continuous Delivery","de-de/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery.yml","de-de/blog/how-to-use-oci-images-as-the-source-of-truth-for-continuous-delivery",{"_path":738,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":739,"content":745,"config":751,"_id":753,"_type":13,"title":754,"_source":15,"_file":755,"_stem":756,"_extension":18},"/de-de/blog/journey-through-gits-20-year-history",{"ogTitle":740,"schema":741,"ogImage":742,"ogDescription":743,"ogSiteName":671,"noIndex":6,"ogType":672,"ogUrl":744,"title":740,"canonicalUrls":744,"description":743},"20 Jahre GitLab: Begib dich mit uns auf eine Reise","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"20 Jahre GitLab: Begib dich mit uns auf eine Reise\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2025-04-14\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097380/Blog/Hero%20Images/Blog/Hero%20Images/git-20-years-opt2_TWNsNk8KH43b3jP0KLD0U_1750097380123.png","Begib dich mit uns auf die Spuren des ersten Commits, die einzigartigen Aspekte der frühen Releases und die Verwirrung, die ein Update des Standardverhaltens von git-push(1) ausgelöst hat.","https://about.gitlab.com/blog/journey-through-gits-20-year-history",{"heroImage":742,"body":746,"authors":747,"updatedDate":748,"date":749,"title":740,"tags":750,"description":743,"category":679},"Das Git-Projekt ist gerade 20 Jahre alt geworden. In diesen Jahren ist viel\npassiert – während das konzeptionelle Design von\n[GitLab](https://about.gitlab.com/de-de/) seit seiner Entstehung nicht\nwesentlich verändert wurde, hat sich doch die Art und Weise, wie\nBenutzer(innen) mit dem Tool interagieren, deutlich geändert. Wir bei GitLab\nsind stolz darauf, auf dieser wichtigen Software aufzubauen und Teil ihrer\nErfolgsgeschichte zu sein.\n\n\nBegleite uns auf einer Reise durch die Geschichte von Git und entdecke, wie sich das System im Laufe der Jahre entwickelt hat.\n\n\n## Der erste Commit\n\n\nDer erste Commit wurde am 7. April 2005 von [Linus Torvalds](https://about.gitlab.com/de-de/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds/), dem Schöpfer des Linux-Kernels, vorgenommen: `e83c5163316 (Initial revision\n\nof \"git\", the information manager from hell, 2005-04-07)`.\n\n\nWie wir sehen können, enthält dieser Commit nicht viele Dateien:\n\n\n```shell\n\n$ git ls-tree e83c5163316\n\n100644 blob a6bba79ba1f46a1bbf7773449c3bd2bb9bf48e8b\tMakefile\n\n100644 blob 27577f76849c09d3405397244eb3d8ae1d11b0f3\tREADME\n\n100644 blob 98a32a9ad39883c6d05a000a68511d4b1ee2b3c7\tcache.h\n\n100644 blob 74a0a234dd346fff51c773aa57d82fc4b83a8557\tcat-file.c\n\n100644 blob 840307af0cfaab31555795ce7175d5e9c9f981a0\tcommit-tree.c\n\n100644 blob 25dc13fe101b219f74007f3194b787dd99e863da\tinit-db.c\n\n100644 blob c924a6e0fc4c36bad6f23cb87ee59518c771f936\tread-cache.c\n\n100644 blob 1b47742d8cbc0d98903777758b7b519980e7499e\tread-tree.c\n\n100644 blob b8522886a15db861508fb6d03d4d88d6de912a4b\tshow-diff.c\n\n100644 blob 5085a5cb53ee52e1886ff6d46c609bdb2fc6d6cd\tupdate-cache.c\n\n100644 blob 921f981353229db0c56103a52609d35aff16f41b\twrite-tree.c\n\n```\n\n\nNeben der Build-Infrastruktur bietet der erste Commit sieben Top-Level-Befehle:\n\n\n- `init-db` zum Initialisieren eines neuen Git-Repositorys\n\n- `update-cache` zum Hinzufügen von Dateien zum Index\n\n- `write-tree`, um den Inhalt des Index heranzuziehen und daraus einen neuen Baum zu erstellen\n\n- `read-tree` zum Lesen eines Baum-Objekts\n\n- `commit-tree` zum Erstellen eines Commits aus einem Baum\n\n- `cat-file` zum Lesen eines spezifischen Objekts in eine temporäre Datei\n\n\nBeachte, dass der Befehl `git` zu der Zeit noch gar nicht existierte.\n\n\nStattdessen mussten diese Befehle direkt ausgeführt werden.\n\n\nErstellen wir zum Beispiel ein neues Repository:\n\n\n```shell\n\n$ mkdir repo\n\n$ cd repo\n\n$ init-db\n\ndefaulting to private storage area\n\n$ ls -a\n\n.  ..  .dircache\n\n```\n\n\nDas sieht ziemlich unbekannt aus: Es gibt kein `.git`-Verzeichnis, aber dafür gibt es das Verzeichnis `.dircache`. Und wo war der private Speicherbereich?\n\n\nDas frühe Design von Git unterschied zwischen einem „geteilten“ und einem „privaten“ Objektspeicherbereich. In diesem Objektspeicherbereich befanden sich alle Git-Objekte. Zum Beispiel deine Commits und Blobs.\n\n\nStandardmäßig erstellte `init-db` einen privaten Objektspeicherbereich, der nur für das verwaltete Verzeichnis verwendet wurde, in dem es erstellt wurde. Ein „geteilter“ Objektspeicherbereich hingegen teilte Objektinhalte über mehrere verwaltete Verzeichnisse, so dass dasselbe Objekt nicht zweimal gespeichert werden musste.\n\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n\n### Einen Commit erstellen\n\n\nWir haben nun ein Repository, doch wie wurde damals ein Commit erstellt? Das war nicht ganz so einfach wie heute mit `git add . && git commit`. Stattdessen musste man wie folgt vorgehen:\n\n\n1. Man musste den Index aktualisieren, indem man `update-cache` für jede Datei aufrief, die man hinzufügen wollte.\n\n2. Dann schrieb man einen neuen Baum, indem man `write-tree` aufrief, wodurch alles herangezogen wurde, was zum Index hinzugefügt worden war.\n\n3. Man richtete Umgebungsvariablen ein, um Git mitzuteilen, wer man ist.\n\n4. Dann schrieb man ein Commit-Objekt, indem man `commit-tree` aufrief.\n\n\nErstellen wir einen Commit im Repository:\n\n\n```shell\n\n$ echo content-1 >file-a\n\n$ update-cache file-a\n\n$ echo content-2 >file-b\n\n$ update-cache file-b\n\n$ write-tree\n\n3f143dfb48f2d84936626e2e5402e1f10c2050fb\n\n$ export COMMITTER_NAME=\"Patrick Steinhardt\"\n\n$ export COMMITER_EMAIL=ps@pks.im\n\n$ echo \"commit message\" | commit-tree 3f143dfb48f2d84936626e2e5402e1f10c2050fb\n\nCommitting initial tree 3f143dfb48f2d84936626e2e5402e1f10c2050fb\n\n5f8e928066c03cebe5fd0a0cc1b93d058155b969\n\n```\n\n\nDas ist nicht gerade ergonomisch, aber es funktioniert! Werfen wir einen Blick auf den generierten Commit:\n\n\n```shell\n\n$ cat-file 5f8e928066c03cebe5fd0a0cc1b93d058155b969\n\ntemp_git_file_rlTXtE: commit\n\n$ cat temp_git_file_rlTXtE\n\ntree 3f143dfb48f2d84936626e2e5402e1f10c2050fb\n\nauthor Patrick Steinhardt \u003Cps@pks.im> Wed Mar 26 13:10:16 2025\n\ncommitter Patrick Steinhardt \u003Cps@pks.im> Wed Mar 26 13:10:16 2025\n\n\ncommit message\n\n```\n\n\nBeachte, dass `cat-file` den Inhalt nicht direkt gedruckt hat, sondern ihn zuerst in eine temporäre Datei geschrieben hat. Der Inhalt der Datei sieht jedoch genauso aus, wie ein moderner Commit aussehen würde.\n\n\n### Änderungen vornehmen\n\n\nWie können wir nun den Status der Dateien ermitteln? Vielleicht hast du es erraten: mit `show-diff`:\n\n\n```shell\n\n$ show-diff\n\nfile-a: ok\n\nfile-b: ok\n\n\n$ echo modified-content >file-a\n\n$ show-diff\n\n--- -\t2025-03-26 13:14:53.457611094 +0100\n\n+++ file-a\t2025-03-26 13:14:52.230085756 +0100\n\n@@ -1 +1 @@\n\n-content-1\n\n+modified-content\n\nfile-a:  46d8be14cdec97aac6a769fdbce4db340e888bf8\n\nfile-b: ok\n\n```\n\n\nLustigerweise konnte `show-diff` bereits diffs zwischen dem alten und neuen Zustand der geänderten Datei generieren! Git hat das jedoch erreicht, indem es einfach das Unix-Tool diff(1) ausgeführt hat.\n\n\nZusammenfassend lässt sich sagen, dass dies zwar alles noch recht spartanisch war, aber das Nötige bot, um den Verlauf nachzuverfolgen. Es gab aber noch viele Einschränkungen:\n\n\n- Es gab noch keine einfache Möglichkeit, zwischen Commits zu wechseln.\n\n- Es gab keine Möglichkeit, Protokolle anzuzeigen.\n\n- Es gab keine Branches, Tags und nicht einmal Referenzen. Von den Benutzer(inne)n wurde erwartet, dass sie die Objekt-IDs manuell verfolgen.- Es gab keine Möglichkeit, zwei Repositories miteinander zu synchronisieren. Stattdessen wurde von den Benutzer(inne)n erwartet, dass sie „rsync(1)“ verwenden, um die `.dircache`-Verzeichnisse zu synchronisieren.\n\n- Es gab keine Möglichkeit, Merges durchzuführen.\n\n\n## Git 0.99\n\n\nDie erste Testversion von Git war Version 0.99. Diese Release kam nur zwei Monate nach dem ersten Commit auf, enthielt aber bereits 1.076 Commits. Es waren fast 50 verschiedene Entwickler(innen) beteiligt. Der häufigste Commiter war zu diesem Zeitpunkt Linus selbst, dicht gefolgt von Junio Hamano, dem aktuellen Betreuer.\n\n\nViele Dinge hatten sich seit dem ersten Commit geändert:\n\n\n- Git begann, verschiedene Entwicklungs-Branches mithilfe von Referenzen zu verfolgen, wodurch in den meisten Fällen Objekt-IDs nicht mehr manuell nachverfolgt werden mussten.\n\n- Es gab ein neues Remote-Protokoll, das es zwei Repositories ermöglichte, Objekte miteinander auszutauschen.\n\n- Das Verzeichnis `.dircache` wurde in `.git` umbenannt.\n\n- Es wurde möglich, einzelne Dateien zusammenzuführen.\n\n\nDie wichtigste offensichtliche Änderung war jedoch die Einführung des Top-Level-Befehls `git` und seiner Unterbefehle. Interessanterweise wurden mit dieser Version auch die Befehle „Plumbing“ und „Porcelain“ eingeführt:\n\n\n- „Plumbing“-Tools sind Low-Level-Befehle, die auf das zugrunde liegende Git-Repository zugreifen.\n\n- „Porcelain“-Tools sind Shell-Skripte, die die Plumbing-Befehle einpacken, um eine schönere, hochwertige Benutzeroberfläche zu bieten.Diese Aufteilung existiert auch heute noch, wie in [`git(1)`](https://git-scm.com/docs/git#_high_level_commands_porcelain) dokumentiert ist. Da die meisten Porcelain-Tools jedoch von Shell-Skripten zu C umgeschrieben wurden, verschwimmt die Trennung zwischen den beiden Kategorien mittlerweile deutlich.\n\n\n## Linus übergibt die Leitung\n\n\nLinus hat Git nie gegründet, weil sein Herz für Versionskontrollsysteme schlägt, sondern weil er für die Entwicklung des Linux-Kernels eine brauchbare Alternative zu BitKeeper suchte. Daher hatte er nie vor, Git für immer zu leiten. Die Absicht war, es so lange zu leiten, bis er eine(n) vertrauenswürdige(n) Nachfolger(in) gefunden hatte.\n\n\nDieser Jemand war Junio Hamano. Junio stieg etwa eine Woche nach dem ersten Commit von Linus bei Git ein und hatte nach der Veröffentlichung von Git 0.99 bereits einige hundert Commits im Verlauf. Am 26. Juli 2005 machte [Linus daher Junio zum neuen Betreuer des Git-Projekts](https://lore.kernel.org/git/Pine.LNX.4.58.0507262004320.3227@g5.osdl.org/). Linus trug zwar weiter zu Git bei, doch seine Beteiligung wurde nach und nach immer weniger – nicht verwunderlich, da er als Leiter des Linux-Projektes ziemlich beschäftigt ist.\n\n\nJunio leitet das Git-Projekt auch heute noch.\n\n\n> Lies unser großes [Interview mit Linus Torvalds](https://about.gitlab.com/de-de/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds/) und erfahre noch mehr über die Geschichte von Git.\n\n\n## Git 1.0\n\n\nDie erste größere Version von Git wurde am 21. Dezember 2005 von Junio veröffentlicht. Interessanterweise gab es 34 Releases zwischen Version 0.99 und Version 1.0: 0.99.1 bis 0.99.7, 0.99.7a bis 0.99.7d, 0.99.8 bis 0.99.8g und 0.99.9 bis 0.99.9n.\n\n\nEiner der wichtigsten Meilensteine seit Version 0.99 war wahrscheinlich der Befehl `git-merge(1)`, der hinzugefügt wurde und mit dem man zwei Bäume zusammenführen kann. Dies ist eine enorme Veränderung zu vorher, wo man im Grunde die Zusammenführungen Datei für Datei skripten musste.\n\n\n### Remotes\n\n\nEine weitere wesentliche Änderung war die Einführung der Kurzschreibweise für Remote-Repositories. Während Git bereits wusste, wie man mit Remote-Repositories kommuniziert, mussten Benutzer(innen) jedes Mal die URL angeben, von der sie abrufen wollten, um Änderungen daran vorzunehmen. Dies war ziemlich unpraktisch für die Benutzer(innen), da sie im Normalfall immer wieder mit demselben Remote interagieren wollten.\n\n\nDu weißt vielleicht, wie Remotes jetzt funktionieren, aber der Vorgang war damals noch deutlich anders. Es gab keinen `git-remote(1)`-Befehl, mit dem man seine Remotes verwalten konnte. Remotes wurden nicht einmal in der Datei `.git/config` gespeichert. Als Remotes in Version 0.99.2 eingeführt wurden, *gab* es in Git nicht einmal Konfigurationsdateien.\n\n\nStattdessen musste man Remotes konfigurieren, indem man eine Datei in das Verzeichnis `.git/branches` schrieb, was dem heutigen Empfinden nach gegen jegliche Intuition geht. Aber der Mechanismus funktioniert auch heute noch:\n\n\n```shell\n\n$ git init repo --\n\nInitialized empty Git repository in /tmp/repo/.git/\n\n$ cd repo\n\n$ mkdir .git/branches\n\n$ echo https://gitlab.com/git-scm/git.git >.git/branches/origin\n\n$ git fetch origin refs/heads/master\n\n```\n\n\nAber das ist noch nicht alles! Das Verzeichnis wurde bald darauf mit der Git-Version 0.99.5 in „remotes“ umbenannt, also gibt es in einem modernen Git-Client insgesamt drei verschiedene Möglichkeiten, Remotes zu konfigurieren.\n\n\nDie meisten von euch haben wahrscheinlich weder `.git/branches` noch `.git/remotes` verwendet, denn beide Mechanismen gelten seit 2005 bzw. 2011 als veraltet. Darüber hinaus werden diese Verzeichnisse in Git 3.0 endgültig entfernt.\n\n\n## Git-Branding\n\n\nIm Jahr 2007 wurde das erste Git-Logo erstellt. Ob man das schon als Logo bezeichnen kann, ist fraglich, da es nur aus drei roten Minuszeichen über drei grünen Pluszeichen bestand. Dies sollte widerspiegeln, wie die Ausgabe von `git diff` aussah:\n\n\n![Drei rote Minuszeichen über drei grünen Pluszeichen, die die Ausgabe von `git diff` widerspiegeln](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097387927.png)\n\n\nEtwas später, im Jahr 2008, wurde die Website [git-scm.com](https://git-scm.com) veröffentlicht:\n\n\n![Startseite für git-scm.com im Jahr 2006](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097387930.png)\n\n\nIm Jahr 2012 wurde die Git-Webseite von Scott Chacon und Jason Long [überarbeitet](https://lore.kernel.org/git/CAP2yMaJy=1c3b4F72h6jL_454+0ydEQNXYiC6E-ZeQQgE0PcVA@mail.gmail.com/). Sie sieht ziemlich ähnlich aus wie heute:\n\n\n![Die Git-Website wurde 2012 überarbeitet](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097387932.png)\n\n\nDieses neue Design der Website weist das neue rot-orangefarbene Logo von Jason Long auf, das auch derzeit verwendet wird:\n\n\n![Git-Logo](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097388/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097387934.png)\n\n\n## Git 2.0\n\n\nGit begann schon in der Version 1.0, dem modernen Git sehr ähnlich zu sehen. Daher folgt nun der große historische Sprung zu Git 2.0. Diese Version wurde etwa 10 Jahre nach Git 1.0 veröffentlicht und war die erste Version, die absichtlich abwärtskompatible Änderungen in zentralen Workflows enthielt.\n\n\n### Standardverhalten von `git-push(1)`\n\n\nDie Änderung, die wohl die meiste Verwirrung in dieser Version verursachte, war das geänderte Standardverhalten von `git-push(1)`.\n\n\nEs gibt ein paar verschiedene Aktionen, die Git ausführen kann, wenn du in ein Remote-Repository pusht und nicht genau angibst, was genau du pushen möchtest:\n\n\n- Git kann verweigern, irgendetwas zu tun, und bittet dich um weitere Informationen darüber, was genau du pushen möchtest.\n\n- Git kann den aktuell ausgecheckten Branch pushen.\n\n- Git kann den aktuell ausgecheckten Branch pushen, aber nur, wenn es weiß, dass es ein Äquivalent auf der Remote-Seite gibt.\n\n- Git kann alle deine Branches pushen, die ein Äquivalent auf der Remote-Seite haben.\n\n\nDas Verhalten des modernen Git ist die sogenannte „einfache“ Strategie, also die dritte der oben angeführten Optionen. Vor Git 2.0 war das Standardverhalten jedoch die „Matching“-Strategie, also die letzte der genannten Optionen.\n\n\nDie „Matching“-Strategie war deutlich riskanter. Man musste vor dem Pushen immer sicherstellen, dass es in Ordnung war, alle lokalen Branches zu pushen, die ein Äquivalent auf der Remote-Seite haben. Andernfalls hätte man möglicherweise unbeabsichtigt Änderungen gepusht. Daher wurde beschlossen, die Strategie auf die „einfache“ Strategie zu ändern, um das Risiko zu verringern und Einsteiger(inne)n die ersten Schritte mit Git zu erleichtern.\n\n\n### `git-add(1)`\n\n\nEine weitere große Änderung war das Standardverhalten von `git-add(1)` im Hinblick auf nachverfolgte Dateien, die gelöscht wurden. Vor Git 2.0 hätte `git-add(1)` gelöschte Dateien nicht automatisch gestaged, sondern du hättest jede gelöschte Datei manuell mit `git-rm(1)` hinzufügen müssen, damit sie Teil des Commits ist. Mit Git 2.0 wurde dieses Verhalten geändert, sodass `git-add(1)` auch gelöschte Dateien zum Index hinzufügt.\n\n\n## Wir feiern die Git-Community\n\n\nIch werde dich nicht mit Details darüber langweilen, wie Git heute funktioniert – du nutzt es wahrscheinlich ohnehin täglich, und wenn nicht, gibt es viele tolle Tutorials, die dir beim Einstieg helfen. Stattdessen wollen wir die Git-Community hochleben lassen – sie ist es nämlich, dank der Git auch 20 Jahre später noch wunderbar funktioniert.\n\n\nIm Laufe der Zeit hat Git:\n\n\n- 56 721 Commits seit der Veröffentlichung von Git 2.49 erhalten.\n\n- Beiträge von mehr als 2 000 verschiedenen Personen erhalten.\n\n- 60 Hauptversionen veröffentlicht.Das Git-Projekt hat auch einen stetigen Zustrom neuer Mitwirkender durch die Teilnahme am [Google Summer of Code](https://summerofcode.withgoogle.com/) und [Outreachy](https://www.outreachy.org/) erfahren. Neue Mitwirkende wie diese werden dafür sorgen, dass das Git-Projekt auch langfristig weitergeführt wird.\n\n\nDaher möchte ich allen Mitwirkenden von Herzen danken. Es sind eure Beiträge, die Git erst möglich gemacht haben.\n\n\n## Ein Blick in die Zukunft\n\n\nEs steht außer Frage, dass Git den Wettlauf um das beste Versionskontrollsystem gewonnen hat. Es hat einen bedeutenden Marktanteil, und es ist nicht einfach, Open-Source-Projekte zu finden, die ein anderes Versionskontrollsystem als Git verwenden. Git hat also eindeutig vieles richtig gemacht.\n\n\nDennoch ist die Entwicklung nicht stillgestanden und auch in Zukunft werden viele Herausforderungen auf Git warten. Einerseits sind das technische Herausforderungen:\n\n- Modernisierung einer alternden Codebasis\n\n- Skalierung mit der ständig wachsenden Größe von Monorepos\n\n- Bessere Handhabung großer Binärdateien\n\n\nAndererseits tauchen Probleme sozialer Art auf:\n\n- Verbesserung der Benutzerfreundlichkeit von Git\n\n- Förderung der Git-Community, damit das Projekt langfristig gesund bleibt\n\n\nEs gibt immer noch viel zu tun und wir bei GitLab sind stolz darauf, Teil dieser Bemühungen zu sein. Gemeinsam können wir sicherstellen, dass Git auch in den nächsten 20 Jahren ein so fantastisches Versionskontrollsystem bleibt.\n\n\n## Erfahre mehr über Git\n\n\n- [Wir feiern das 20-jährige Git-Jubiläum mit dessen Erfinder Linus Torvalds](https://about.gitlab.com/de-de/blog/celebrating-gits-20th-anniversary-with-creator-linus-torvalds/)\n\n- [Was gibt es Neues in Git 2.49.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-49-0/)\n\n- [Was gibt es Neues in Git 2.48.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-48-0/)\n\n- [Der Anfängerleitfaden zum „reftable“-Format von Git](https://about.gitlab.com/de-de/blog/a-beginners-guide-to-the-git-reftable-format/)\n",[676],"2025-05-20","2025-04-14",[681,9],{"slug":752,"featured":90,"template":685},"journey-through-gits-20-year-history","content:de-de:blog:journey-through-gits-20-year-history.yml","Journey Through Gits 20 Year History","de-de/blog/journey-through-gits-20-year-history.yml","de-de/blog/journey-through-gits-20-year-history",{"_path":758,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":759,"content":765,"config":773,"_id":775,"_type":13,"title":776,"_source":15,"_file":777,"_stem":778,"_extension":18},"/de-de/blog/keep-git-history-clean-with-interactive-rebase",{"title":760,"description":761,"ogTitle":760,"ogDescription":761,"noIndex":6,"ogImage":762,"ogUrl":763,"ogSiteName":671,"ogType":672,"canonicalUrls":763,"schema":764},"Git-Historie mit Interactive Rebase bereinigen","Erfahre, was Git Rebase ist und wie du damit in ein paar Schritten eine Git-Historie bereinigen kannst.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662593/Blog/Hero%20Images/title-image.png","https://about.gitlab.com/blog/keep-git-history-clean-with-interactive-rebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git-Historie mit Interactive Rebase bereinigen\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tobias Günther\"}],\n        \"datePublished\": \"2020-11-23\",\n      }",{"title":760,"description":761,"authors":766,"heroImage":762,"date":768,"body":769,"category":770,"tags":771,"updatedDate":772},[767],"Tobias Günther","2020-11-23","# Git-Historie mit dem Interactive Rebase bereinigen\n\n\nDas interaktive Rebase ist eines der vielseitigsten Tools von Git. Hier\nerfährst du, wie du damit Commit-Meldungen korrigierst, Fehler behebst und\ndeine Git-Historie ordentlich hältst. \n\n\n## Was ist das Interactive Rebase?\n\n\nDas Interactive [Rebase](/solutions/source-code-management/),\nauch bekannt als Git Interactive Rebase, wird oft als das „Schweizer\nTaschenmesser\" von Git bezeichnet, da es vielfältige Tools für\nunterschiedliche Einsatzmöglichkeiten bietet. Ein zentraler und wichtiger\nAnwendungsbereich ist das Bereinigen der eigenen lokalen Commit-Historie. \n\n\nBeachte hierbei das Wort „lokal”: Es sollte ausschließlich verwendet werden,\num die persönliche Commit-Historie aufzuräumen, z.B. wenn du einen\nFeature-Branch in einen Team-Branch integrierst. Es ist hingegen nicht\ngeeignet für Commits, die bereits an ein entferntes Repository gepusht und\nsomit geteilt wurden, da interaktives Rebase die Git-Historie „umschreibt”.\nIm Folgenden findest du einige Beispiel-Szenarien.\n\n\nAnmerkung: Zur besseren Visualisierung der Szenarios und Workflows in diesem\nBeitrag habe ich das [\"Tower\" Git Desktop\nGUI](https://www.git-tower.com/?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase)\nin einigen der Screenshots verwendet.\n\n{: .note}\n\n\n## Korrektur einer alten Commit-Nachricht mit Git Rebase Interactive\n\n\nEs ist möglich, dass du nach getaner Arbeit einen Tippfehler in einer\n**älteren Commit-Nachricht** entdeckst oder merkst, dass eine wichtige\nInformation in der Beschreibung fehlt. Wäre es der allerletzte Commit,\nkönnte man einfach die Option '--amend' des 'git commit' Befehls nutzen, um\ndie Nachricht zu korrigieren. Bei älteren Commits jedoch ist ein\ninteraktives Rebase notwendig, um Änderungen vorzunehmen.\n\n\nHier ein Beispiel für eine fehlerhafte Commit-Nachricht, die du korrigieren\nmöchtest:\n\n\n![A bad commit message that needs\ncorrection](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/bad-commit-message@2x.png){:\n.shadow.medium.center}\n\nEine fehlerhafte Commit-Meldung, die korrigiert werden muss\n\n{: .note.text-center}\n\n\nBei jeder interaktiven Rebase-Sitzung mit Git musst du zunächst bestimmen,\n**welchen Teil der Commit-Historie du bearbeiten willst.** Um den\nfehlerhaften Commit aus dem vorherigen Beispiel zu ändern, sollte die\nSitzung beim übergeordneten Commit beginnen.\n\n\n![Starting our interactive rebase\nsession](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/start-at-parent-commit@2x.png){:\n.shadow.medium.center}\n\nStart der interaktiven Rebase-Sitzung\n\n{: .note.text-center}\n\n\nDu kannst nun den Hash dieses Start-Commits an den interaktiven Befehl Git\nRebase weitergeben:\n\n\n```\n\n$ git rebase -i 0023cddd\n\n```\n\n\nNun öffnet sich ein Editor-Fenster, in dem eine Liste der ausgewählten\nCommits zur Bearbeitung angezeigt wird. Dabei kann es überraschend sein,\ndass die Commits in *umgekehrter Reihenfolge* aufgelistet sind. Dies liegt\ndaran, dass Git in einer interaktiven Rebase-Sitzung die alten Commits\nschrittweise erneut anwendet. Aus der Perspektive von Git ist diese\numgekehrte Reihenfolge daher korrekt.\n\n\n![Editor window with the selected\ncommits](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/editor-window-start-ir@2x.png){:\n.shadow.medium.center}\n\nEditor-Fenster mit den ausgewählten Commits\n\n{: .note.text-center}\n\n\nEin wichtiger Hinweis zum Editor-Fenster: *Du kannst die Commit-Nachricht\nnicht direkt in diesem Fenster ändern!* Stattdessen verwendest du ein Action\nKeyword (Aktionsschlüsselwort), um den Commit auszuwählen, den du bearbeiten\nmöchtest. Möchtest du die Nachricht eines Commits ändern, markierst du die\nentsprechende Zeile mit „reword”. Nachdem du das Editor-Fenster gespeichert\nund geschlossen hast, öffnet sich ein neues Fenster, in dem die alte\nCommit-Nachricht angezeigt wird. Hier kannst du nun die gewünschten\nÄnderungen vornehmen.\n\n\n![Finally, we can make our\nchanges](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/correct-commit-message.gif){:\n.shadow.medium.center}\n\nDurchführung der Commit-Änderungen\n\n{: .note.text-center}\n\n\nNach erneutem Speichern und Schließen ist die interaktive Rebase-Sitzung\nabgeschlossen und die alte Commit-Nachricht wurde korrigiert!\n\n\n## Kombinieren mehrerer Commits mit interaktivem Rebase\n\nEin weiterer Anwendungsfall für das interaktive Rebase ist **das\nZusammenfassen mehrerer alter Commits zu einem einzigen** – mithilfe von Git\nRebase Interactive Merge Commits. Obwohl die goldene Regel der\nVersionskontrolle empfiehlt, eher mehrere kleinere Commits als wenige große\nzu erstellen, gibt es Situationen, in denen das Zusammenführen sinnvoll ist.\nBeispielsweise kann es vorkommen, dass du rückblickend feststellst, dass ein\nCommit effektiver ist als mehrere.\n\n\n![Let's combine multiple commits into\none](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-selected-commits@2x.png){:\n.shadow.medium.center}\n\nKombinieren von mehrerer Commits zu einem\n\n{: .note.text-center}\n\n\nWie im ersten Fall beginnt die interaktive Rebase-Sitzung spätestens beim\nübergeordneten Commit, das manipuliert werden soll.\n\n```\n\n$ git rebase -i 2b504bee\n\n```\n\n\nEs öffnet sich wieder ein Editor-Fenster, in dem der Teil der\nCommit-Historie aufgelistet ist, der bearbeitet werden soll:\n\n\n![Marking lines with\n\"squash\"](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-mark-commit@2x.png){:\n.shadow.medium.center}\n\nLinien in der Commit-Historie mit „Squash“ markieren\n\n{: .note.text-center}\n\n\nDas hier verwendete Action Keyword heißt „squash“. Um es zu verwenden, musst\ndu noch etwas über „squash“ wissen: *Die Zeile, die wir mit dem\nSchlüsselwort „squash“ markieren, wird mit der Zeile direkt darüber\nkombiniert.* Deshalb wurde, wie im Screenshot zu sehen, die Zeile Nr. 2 mit\n„squash“ markiert, um sie mit der Zeile Nr. 1 zu kombinieren.\n\n\nJetzt kannst du das Editor-Fenster speichern und schließen. Danach erscheint\nein neues Fenster, in dem du aufgefordert wirst, eine Commit-Nachricht für\nden neuen Commit einzugeben, der durch die Kombination der beiden alten\nCommits erzeugt wird. So entstehen neue Git Interactive Rebase Merge\nCommits.\n\n\n![Entering a new message for the new, squashed\ncommit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-enter-new-message@2x.png){:\n.shadow.medium.center}\n\nEingabe einer neuen Nachricht für den „squash“-Commit\n\n{: .note.text-center}\n\n\nNach dem Speichern und Schließen dieses Editor-Fensters siehst du, dass ein\nneuer Commit erstellt wurde, der die Change-Sets (Änderungssätze) der beiden\nalten Commits enthält.\n\n\n## Behebung eines Fehlers mit Interactive Rebase\n\nEin weiteres Einsatzgebiet für das interaktive Rebase ist die Korrektur\neines Fehlers in einer früheren Übertragung. Es spielt keine Rolle, welche\nArt von Fehler gemacht wurde: Vielleicht wurde eine wichtige Änderung\nvergessen, eine Datei hätte gelöscht werden sollen oder es wurde einfach ein\nTippfehler gemacht.\n\n\nIn solchen Fällen könnte die erste Reaktion sein, einfach einen neuen Commit\nzu erstellen, der den Fehler behebt. Dies kann jedoch die Commit-Historie\nunübersichtlich machen. Ständig einen ursprünglichen Commit zu erstellen und\ndann einen weiteren, nur um kleine Fehler zu korrigieren, kann zu einer\nchaotischen und schwer nachvollziehbaren Commit-Historie führen.\n\n\nAn dieser Stelle kommt „fixup\", eines der Tools, die mit interaktivem Rebase\ngeliefert werden, zum Einsatz. Git Rebase Interactive Fixup nimmt diesen\n„Quick-Fix\"-Commit, wendet seine Änderungen auf den ursprünglichen Commit\nan, korrigiert ihn und entfernt dann den korrigierenden Commit\n(Band-Aid-Commit):\n\n\n![How \"fixup\"\nworks](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/diagram-fixup.png){:\n.medium.center}\n\nSo funktioniert \"fixup\"\n\n{: .note.text-center}\n\n\nNach der Korrektur scheint es, als ob es nie ein Problem mit dem\nursprünglichen Commit gegeben hätte. Hier ist ein weiteres praktisches\nBeispiel für diesen Prozess.\n\n\nZunächst solltest du alles tun, was nötig ist, um das Problem zu beheben:\nDas kann das Hinzufügen einer neuen Datei, das Ändern bestehender Dateien\noder das Löschen veralteter Dateien sein. Der nächste Schritt ist, diese\nÄnderungen an das Repository zu senden.\n\n\nHierbei nutzt du beim Commit die Option '--fixup' und gibst den Commit-Hash\ndes fehlerhaften Commits an, um Git deutlich zu machen, welcher\nursprüngliche Commit korrigiert werden soll.\n\n\n```\n\n$ git add corrections.txt\n\n$ git commit --fixup 2b504bee\n\n```\n\n\nWenn du dir nun die Commit-Historie anschaust, wirst du feststellen, dass\nein recht gewöhnlich aussehender Commit erstellt wurde, der zunächst einmal\nwenig spektakulär scheint. Bei genauerer Betrachtung aber wirst du bemerken,\ndass doch etwas Unerwartetes passiert ist: Dem neuen Commit wurde\nautomatisch „fixup!“ gefolgt vom Betreff des fehlerhaften Commits\nvorangestellt – pure Magie!\n\n\n![The original commit and the fix\ncommit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_create-fix-commit@2x.png){:\n.shadow.medium.center}\n\nDie ursprüngliche Übertragung und die Korrekturübertragung\n\n{: .note.text-center}\n\n\nDer dritte – wieder etwas gewöhnlichere – Schritt besteht nun darin, die\ninteraktive Rebase-Sitzung zu starten. Auch hier wählst du den Parent der\nfehlerhaften Übertragung als Startpunkt:\n\n```\n\n$ git rebase -i 0023cddd --autosquash\n\n```\n\n\nAls Nächstes verwendest du die Option '--autosquash'. Diese Option sorgt\ndafür, dass du in dem nun geöffneten Editor-Fenster selbst nichts ausführen\nmusst.Wir schauen uns das mal genau an:\n\n\n![Our fix commit is marked \"fixup\" and sorted to the right\nposition](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_editor@2x.png){:\n.shadow.medium.center}\n\nDer Fix-Commit wird als „fixup\" markiert und an die richtige Position\nsortiert\n\n{: .note.text-center}\n\n\nGit hat automatisch zwei Dinge gemacht:\n\n\n1. Es hat den zu korrigierenden Commit als „fixup\" markiert.\n\n2. Es hat die Zeilen neu sortiert, sodass der zu korrigierende Commit direkt\nunter dem fehlerhaften Commit erscheint. Das liegt daran, dass „fixup“ genau\nwie „squash“ funktioniert, indem es mit der darüber liegenden Zeile\nkombiniert wird.\n\n\nNun speicherst du das Editor-Fenster und schließt es dann.\n\n\nDer Commit-Verlauf sieht nun so aus:\n\n\n![A happy\nending!](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_final-corrected@2x.png){:\n.shadow.medium.center}\n\nEin Happy End!\n\n{: .note.text-center}\n\n\nNun sind nicht nur die Korrekturen aus dem „Band-Aid-Commit“ in den\nursprünglich fehlerhaften Commit integriert worden, sondern der fehlerhafte\nCommit ist auch aus der Commit-Historie verschwunden. Alles ist nun so\nbereinigt, dass es scheint, als hätte es nie ein Problem gegeben.\n\n\n## Entdecke die Leistungsfähigkeit von Git Rebase Interactive\n\n\nWie du gesehen hast, gibt es für interaktives Rebase viele\nEinsatzmöglichkeiten, vor allem im Bereich der Fehlerbehebung. Für einen\nÜberblick über weitere nützliche Anwendungen ist das **kostenlose** [\"First\nAid Kit for\nGit\"](https://www.git-tower.com/learn/git/first-aid-kit?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase)\nempfehlenswert. Diese Sammlung besteht aus kurzen Videos (2-3 Minuten pro\nEpisode), die dir zeigen, wie du Fehler mit interaktivem Rebase und anderen\nGit-Tools rückgängig machen kannst.\n\n\n## Weitere Git-Tipps und -Tricks\n\n\n- [15 Git tips to improve your\nworkflow](/blog/15-git-tips-improve-workflow/)\n(englischsprachiger Artikel)\n\n- [How Git Partial Clone lets you fetch only the large file you\nneed](/blog/partial-clone-for-massive-repositories/)\n(englischsprachiger Artikel)\n\n- [Git happens! 6 Common Git mistakes and how to fix\nthem](/blog/git-happens/) (englischsprachiger Artikel)\n\n\n### Über den Gastautor\n\n\n_[Tobias Günther](https://twitter.com/gntr) ist der CEO von\n[Tower](https://www.git-tower.com/?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase),\nder beliebten Git-Desktopanwendung, welche bereits über 100.000\nEntwicklerinnen und Entwickler dabei geholfen hat, noch produktiver zu\nwerden._\n\n\nCoverbild von [David Taljat](https://www.pexels.com/@david-taljat-3748658)\nbei\n[Pexels](https://www.pexels.com/photo/yellow-and-blue-line-on-gray-asphalt-road-5690623/)\n\n{: .note}\n","engineering",[9,729],"2024-12-18",{"slug":774,"featured":6,"template":685},"keep-git-history-clean-with-interactive-rebase","content:de-de:blog:keep-git-history-clean-with-interactive-rebase.yml","Keep Git History Clean With Interactive Rebase","de-de/blog/keep-git-history-clean-with-interactive-rebase.yml","de-de/blog/keep-git-history-clean-with-interactive-rebase",{"_path":780,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":781,"content":787,"config":795,"_id":797,"_type":13,"title":798,"_source":15,"_file":799,"_stem":800,"_extension":18},"/de-de/blog/keeping-git-commit-history-clean",{"title":782,"description":783,"ogTitle":782,"ogDescription":783,"noIndex":6,"ogImage":784,"ogUrl":785,"ogSiteName":671,"ogType":672,"canonicalUrls":785,"schema":786},"4 Situationen, in denen sich eine aufgeräumte Git-Commit-Historie lohnt ","Erfahre, warum eine saubere Git-Commit-Historie die Nachvollziehbarkeit verbessert, Fehler behebt und die Codequalität steigert.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659457/Blog/Hero%20Images/keep-git-commit-history-clean.jpg","https://about.gitlab.com/blog/keeping-git-commit-history-clean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"4 Situationen, in denen sich eine aufgeräumte Git-Commit-Historie lohnt \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kushal Pandya\"}],\n        \"datePublished\": \"2018-06-07\",\n      }",{"title":782,"description":783,"authors":788,"heroImage":784,"date":790,"body":791,"category":770,"tags":792,"updatedDate":794},[789],"Kushal Pandya","2018-06-07","Git-Commits sind einer der Eckpfeiler eines Git-Repositorys. Die\nCommit-Nachrichten sind wie ein Lebensprotokoll für das Repository. Während\nsich das Projekt/Repository im Laufe der Zeit entwickelt – sei es durch das\nHinzufügen neuer Funktionen, das Beheben von Fehlern oder die Überarbeitung\nder Architektur – geben die Commit-Nachrichten Aufschluss darüber, was genau\ngeändert wurde. Daher ist es entscheidend, dass diese Nachrichten die\nzugrunde liegende Änderung präzise und kurz wiedergeben. Die Commit-Historie\nkann leicht verfälscht werden. In diesem Artikel erfährst du, wie du sie\nkorrigieren kannst!\n\n\n## Warum eine aussagekräftige Git-Commit-Historie wichtig ist\n\n\nWas bewirkt ein Git-Commit? Git-Commit-Nachrichten sind die Fingerabdrücke,\ndie du auf dem Code hinterlässt, den du bearbeitest. Wenn du heute einen\nCode festlegst, ist es wichtig, eine klare und aussagekräftige\nCommit-Nachricht zu schreiben, damit du diese auch später noch\nnachvollziehen kannst. Indem Git-Commits kontextabhängig isoliert werden,\nist ein Fehler, der durch einen einzelnen Commit verursacht wurde, schneller\nzu finden. Zudem ist es einfacher, den Commit rückgängig zu machen, der den\nFehler verursacht hat.\n\n\nBei der Arbeit an großen Projekten haben wir oft mit vielen verschiedenen\nKomponenten, die aktualisiert, hinzugefügt oder entfernt werden, zu tun. In\nsolchen Fällen kann es schwierig sein, die Commit-Nachrichten zu pflegen,\ninsbesondere wenn sich die Entwicklung über Tage, Wochen oder sogar Monate\nerstreckt. Um die Wartung eines übersichtlichen Commit-Verlaufs zu\nerleichtern, findest du nachfolgend die vier häufigsten Situationen, mit\ndenen ein Entwickler(innen) bei der Arbeit an einem Git-Repository\nkonfrontiert werden kann.\n\n\n1. Situation 1: Ich muss den letzten Commit ändern\n\n2. Situation 2: Ich muss einen bestimmten Commit ändern\n\n3. Situation 3: Ich muss Commits hinzufügen, entfernen oder kombinieren\n\n4. Situation 4: Mein Commit-Verlauf macht keinen Sinn, ich muss nochmal von\nvorne anfangen\n\n\nBevor wir jedoch tiefer eintauchen, werfen wir einen kurzen Blick auf einen\ntypischen Entwicklungsablauf in unserer hypothetischen Ruby-Anwendung.\n\n\n__Hinweis:__ In diesem Artikel wird vorausgesetzt, dass du mit den\nGrundlagen von Git vertraut bist und weißt, wie Branches funktionieren, wie\nnicht übertragene Änderungen eines Branches zum Staging-Bereich hinzugefügt\nund wie Änderungen übertragen werden. Wenn du unsicher bist, bietet unsere\nDokumentation einen guten Ausgangspunkt.\n\n\n## Beispielprojekt: Neue Navigationsansicht\n\n\nNachfolgend siehst du ein Ruby-on-Rails-Projekt, in dem eine\nNavigationsansicht auf der Homepage hinzugefügt werden muss. Dazu müssen\nmehrere Dateien aktualisiert und hinzugefügt werden. Im Folgenden findest du\neine schrittweise Aufschlüsselung des gesamten Ablaufs:\n\n\n- Du startest die Arbeit an einem Feature, indem du eine einzelne Datei\naktualisierst. Zum Beispiel: `application_controller.rb`\n\n- Für dieses Feature musst du auch eine Ansicht aktualisieren:\n`index.html.haml`\n\n- Du hast einen Teilbereich hinzugefügt, der auf der Indexseite verwendet\nwird: `_navigation.html.haml`\n\n- Die Formatvorlagen für die Seite müssen ebenfalls aktualisiert werden, um\nden hinzugefügten Teil widerzuspiegeln: `styles.css.scss`\n\n- Das Feature ist nun mit den gewünschten Änderungen fertiggestellt. Jetzt\nmusst du die Tests aktualisieren. Dazu gehören die folgenden Dateien:\n  - `application_controller_spec.rb`\n  - `navigation_spec.rb`\n- Die Tests wurden aktualisiert und laufen wie erwartet. Jetzt werden die\nÄnderungen übertragen.\n\n\nDa alle Dateien zu verschiedenen Bereichen der Architektur gehören, werden\ndie Änderungen isoliert voneinander übertragen. Dies gewährleistet, dass\njede Übertragung einen spezifischen Kontext repräsentiert und in einer\nbestimmten Reihenfolge durchgeführt wird. Im Allgemeinen wird die\nReihenfolge von Backend -> Frontend bevorzugt. Dies bedeutet, dass die\nmeisten Backend-bezogenen Änderungen zuerst übertragen werden, gefolgt von\nder mittleren Schicht und dann von den Frontend-bezogenen Änderungen in den\nGit-Commits.\n\n\n1. `application_controller.rb` & `application_controller_spec.rb`:\n__Hinzufügen von Routen für die Navigation.__\n\n2. `_navigation.html.haml` & `navigation_spec.rb`: __Ansicht der\nSeitennavigation.__\n\n3. `index.html.haml`: __Navigation teilweise rendern.__\n\n4. `styles.css.scss`: __Stile für die Navigation hinzufügen.__\n\n\nNachdem die Änderungen übertragen wurden, wird eine Anfrage zur\nZusammenführung mit dem Branch erstellt. Sobald du eine Merge-Anfrage\ngeöffnet hast, wird sie in der Regel von deinem Peer überprüft, bevor die\nÄnderungen im Master-Branch des Repositories zusammengeführt werden. Im\nFolgenden werden die verschiedenen Situationen beschrieben, die bei der\nCodeüberprüfung auftreten können.\n\n\n## Situation 1: Ändern des letzten Git-Commits\n\n\nIm Fall, dass der Prüfer die Datei `styles.css.scss` überprüft und eine\nÄnderung vorgeschlagen hat, ist es recht einfach, die Änderung vorzunehmen,\nda die Stylesheet-Änderungen Teil des __letzten__ Commits in deinem Branch\nsind. So kannst du damit umgehen:\n\n\n- Führe die erforderlichen Änderungen an `styles.css.scss` direkt in deinem\naktuellen Branch durch.\n\n- Sobald du mit den Änderungen fertig bist, füge sie zum Staging-Bereich\nhinzu, indem du `git add styles.css.scss` ausführst.\n\n- Nachdem die Änderungen bereitgestellt wurden, füge sie zu deinem letzten\nCommit hinzu, indem du `git commit --amend` ausführst.\n    - __Aufschlüsselung des Befehls__: Mit dem `git commit`-Befehl werden alle Änderungen, die sich im Staging-Bereich befinden, dem letzten Commit hinzugefügt.\n- Dadurch wird der von Git definierte Texteditor geöffnet, der die\nCommit-Nachricht __„Stile für die Navigation hinzufügen”__ enthält, die\nbereits beim vorherigen Commit festgelegt wurde.\n\n- Da nur die CSS-Deklaration aktualisiert wurde, muss die Commit-Nachricht\nnicht geändert werden. An dieser Stelle kannst du einfach speichern und den\nTexteditor, den Git für dich geöffnet hat, beenden. Deine Änderungen werden\ndann in den Commit übernommen.\n\n\nDa du ein bestehendes Git-Commit geändert hast, müssen diese Änderungen\nzwangsweise in dein Repository übertragen werden. Dazu nutzt du  `git push\n--force-with-lease \u003Cremote_name> \u003Cbranch_name>`. Dieser Befehl überschreibt\ndas Commit `Add styles for navigation` im entfernten Repository mit dem\naktualisierten Commit, das gerade im lokalen Repository vorgenommen wurde.\n\n\nWenn mehrere Personen an einem Branch arbeiten, kann ein erzwungener Push\nvon Branches dazu führen, dass andere Benutzer Probleme bekommen, wenn sie\nversuchen, ihre Änderungen auf einen entfernten Branch zu pushen, in dem\nbereits neue Commits gepusht wurden. Daher sollte diese Funktion mit Bedacht\neingesetzt werden. Weitere Informationen zu den Force-Push-Optionen von Git\nfindest du\n[hier](https://git-scm.com/docs/git-push#git-push---no-force-with-lease\n\"hier\").\n\n\n## Situation 2: Ändern einer bestimmten Git-Commit-Änderung\n\n\nIn der vorherigen Situation war die Änderung des Git-Commits recht einfach,\nda nur der letzte Git-Commit geändert werden musste. Stell dir jedoch vor,\nein Prüfer würde vorschlagen, etwas in `_navigation.html.haml` zu ändern. In\ndiesem Fall handelt es sich um den zweiten Commit von oben, sodass die\nÄnderung nicht so direkt ist wie in der ersten Situation. \n\n\nJeder Commit in einem Branch wird durch eine eindeutige\nSHA-1-Hash-Zeichenkette identifiziert. Diese dient als eine Art eindeutige\nID, die einen Commit von einem anderen unterscheidet. Du kannst alle\nvorherigen Commits zusammen mit ihren SHA-1-Hashes in einem Branch anzeigen,\nindem du den Befehl `git log` ausführst. Das Ergebnis ist eine Liste von\nCommits, wobei die neuesten Commits ganz oben stehen.\n\n\n```\n\ncommit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD ->\nadd-page-navigation)\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 15:24:02 2018 +0530\n\n    Add styles for navigation\n\ncommit c22a3fa0c5cdc175f2b8232b9704079d27c619d0\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:42:52 2018 +0000\n\n    Render navigation partial\n\ncommit 4155df1cdc7be01c98b0773497ff65c22ba1549f\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:42:51 2018 +0000\n\n    Page Navigation View\n\ncommit 8d74af102941aa0b51e1a35b8ad731284e4b5a20\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:12:20 2018 +0000\n\n    Add routes for navigation\n```\n\n\nAn dieser Stelle kommt der Befehl `git rebase` ins Spiel. Wenn wir einen\nbestimmten Commit mit `git rebase` bearbeiten wollen, müssen wir zunächst\nunseren Branch neu erstellen, indem wir HEAD bis zu dem Punkt vor dem Commit\nzurücksetzen, den wir bearbeiten wollen. In unserem Fall müssen wir den\nCommit ändern, der `Page Navigation View` lautet.\n\n\n![Ansicht Page Navigation\nView](https://about.gitlab.com/images/blogimages/keeping-git-commit-history-clean/GitRebase.png){:\n.shadow.center.medium}\n\n\n- Achte auf den Hash des Commits, der direkt vor dem Commit liegt, den wir\nändern möchten. Kopiere den Hash und führe die folgenden Schritte aus:\n\n- Verschiebe den Branch auf einen Commit vor unserem Ziel-Commit; führe `git\nrebase -i8d74af102941aa0b51e1a35b8ad731284e4b5a20` aus.\n    - __Aufschlüsselung der Git-Befehle:__ Hier führen wir den Git-Befehl `rebase` im interaktiven Modus aus und geben einen SHA-1-Hash als Commit an, auf den `rebase` erfolgen soll.\n- Dieser Befehl führt den rebase-Befehl für Git im interaktiven Modus aus\nund öffnet den Texteditor, der alle Commits anzeigt, die auf den Commit\nfolgen, auf den du den `rebase` durchführen möchtest. Der Texteditor sollte\nin etwa so aussehen:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\n\n# Rebase 8d74af10294..aa0a35a867e onto 8d74af10294 (3 commands)\n\n#\n\n# Commands:\n\n# p, pick = use commit\n\n# r, reword = use commit, but edit the commit message\n\n# e, edit = use commit, but stop for amending\n\n# s, squash = use commit, but meld into previous commit\n\n# f, fixup = like \"squash\", but discard this commit's log message\n\n# x, exec = run command (the rest of the line) using shell\n\n# d, drop = remove Git commit\n\n#\n\n# These lines can be re-ordered; they are executed from top to bottom.\n\n#\n\n# If you remove a line here THAT COMMIT WILL BE LOST.\n\n#\n\n# However, if you remove everything, the rebase will be aborted.\n\n#\n\n# Note that empty commits are commented out\n\n```\n\n\nBeachte, dass jedem Commit das Wort `pick` vorangestellt ist. Im Inhalt\nunten sind alle möglichen Schlüsselwörter aufgeführt, die du verwenden\nkannst. Da du eine Übertragung bearbeiten möchtest, musst du `pick\n4155df1cdc7 Page Navigation View in edit 4155df1cdc7 Page Navigation View`\nändern. Speichere die Änderungen und verlasse den Editor.\n\n\nDer Branch wird nun auf den Zeitpunkt vor der Commit-Übergabe zurückgesetzt,\ndie die Datei `_navigation.html.haml` enthielt. Öffne die Datei und führe\ndie gewünschten Änderungen gemäß dem Feedback der Überprüfung durch. Sobald\ndu mit den Änderungen fertig bist, füge sie zum Staging-Bereich hinzu, indem\ndu `git add _navigation.html.haml` ausführst.\n\n\nNachdem die Änderungen bereitgestellt wurden, ist es an der Zeit, den Branch\nHEAD wieder auf den ursprünglichen Commit zurückzusetzen, wobei auch die neu\nhinzugefügten Änderungen berücksichtigt werden. Führe `git rebase\n--continue` aus. Dadurch wird dein Standardeditor im Terminal geöffnet und\nzeigt die Commit-Nachricht an, die während des Rebase bearbeitet wurde; in\ndiesem Fall Page `Navigation View`. Du kannst diese Nachricht ändern, wenn\ndu möchtest – zunächst bleibt sie jedoch unverändert. Speichere und beende\nden Editor.\n\n\nJetzt zeigt Git alle Commits an, die auf den Commit folgten, den du gerade\nbearbeitet hast. Der Branch `HEAD` ist jetzt wieder auf dem ursprünglichen\nobersten Commit. Er enthält auch die neuen Änderungen, die du an einem der\nCommits vorgenommen hast.\n\n\nDa du erneut einen Commit geändert hast, der bereits im entfernten\nRepository vorhanden ist, musst du diesen Branch noch einmal mit `git push\n--force-with-lease \u003Cremote_name> \u003Cbranch_name>` pushen.\n\n\n## Situation 3: Hinzufügen, Entfernen oder Kombinieren von Git-Commits\n\n\nEs kommt häufig vor, dass mehrere Commits gemacht wurden, nur um etwas zu\nkorrigieren, das bereits zuvor committed wurde. Jetzt möchtest du diese\nCommits so weit wie möglich reduzieren und mit den ursprünglichen Commits\nkombinieren.\n\n\nDazu musst du einfach den interaktiven Rebase wie in den anderen Szenarien\nstarten.\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\npick 62e858a322 Fix a typo\n\npick 5c25eb48c8 Ops another fix\n\npick 7f0718efe9 Fix 2\n\npick f0ffc19ef7 Argh Another fix!\n\n```\n\n\nNun stell dir vor, du möchtest all diese Korrekturen in `c22a3fa0c5c Render\nnavigation partial` kombinieren. Dazu musst du nur Folgendes tun:\n\n\n1. Verschiebe die Korrekturen nach oben, sodass sie sich direkt unter der\nCommit-Übergabe befinden, die du am Ende behalten möchtest.\n\n2. Ändere `pick` auf `squash` oder `fixup` für jede der Korrekturen.\n\n\n*Hinweis:* `squash` behält die Commit-Nachrichten der Git-Fixes in der\nBeschreibung bei. `fixup` vergisst die Commit-Nachrichten der Fixes und\nbehält das Original bei.\n\nDas Ergebnis sieht dann etwa so aus:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo\n\nfixup 5c25eb48c8 Ops another fix\n\nfixup 7f0718efe9 Fix 2\n\nfixup f0ffc19ef7 Argh Another fix!\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nSpeichere die Änderungen, beende den Editor und schon bist du fertig! Dies\nist der resultierende Verlauf:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick 96373c0bcf Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nWie zuvor musst du jetzt nur noch `git push --force-with-lease \u003Cremote_name>\n\u003Cbranch_name>` ausführen, damit die Änderungen sichtbar sind.\n\n\nWenn du einen Git-Commit vollständig aus dem Branch entfernen möchtest,\nschreibe statt `squash` oder `fixup` einfach `drop` oder lösche diese Zeile.\n\n\n## Vermeiden von Konflikten bei Git-Commits\n\n\nUm Konflikte zu vermeiden, solltest du sicherstellen, dass die Commits, die\ndu in der Zeitleiste nach vorne schiebst, nicht dieselben Dateien berühren,\ndie von den Commits nach ihnen bearbeitet werden.\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo                 # this changes styles.css\n\nfixup 5c25eb48c8 Ops another fix            # this changes image/logo.svg\n\nfixup 7f0718efe9 Fix 2                      # this changes styles.css\n\nfixup f0ffc19ef7 Argh Another fix!          # this changes styles.css\n\npick aa0a35a867e Add styles for navigation  # this changes index.html (no\nconflict)\n\n```\n\n\n## Extra-Tipp: Schnelle Git commit fixups\n\n\nWenn du genau weißt, welchen Commit du reparieren möchtest, musst du beim\nCommit keine Zeit damit verschwenden, dir gute temporäre Namen für \"Fix 1\",\n\"Fix 2\", ..., \"Fix 42\" auszudenken.\n\n\n### Step 1: `--fixup`\n\n\nNachdem du die Änderungen vorgenommen hast, um das zu reparieren, was\nrepariert werden muss, übergibst du einfach alle Änderungen mit Git wie\nfolgt:\n\n\n```\n\ngit commit --fixup c22a3fa0c5c\n\n```\n\n(Dies ist der Hash für den Commit `c22a3fa0c5c Render navigation partial`)\n\nDadurch wird diese Commit-Nachricht erzeugt: `fixup! Render navigation\npartial`.\n\n\n### Step 2: `--autosquash`\n\n\nEinfaches interaktives Rebase. Du kannst `git` die `fixups` automatisch an\nder richtigen Stelle platzieren lassen.\n\n\n`git rebase -i 4155df1cdc7 --autosquash`\n\n\nDer Verlauf wird folgendermaßen dargestellt:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo\n\nfixup 5c25eb48c8 Ops another fix\n\nfixup 7f0718efe9 Fix 2\n\nfixup f0ffc19ef7 Argh Another fix!\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nDu kannst sie einfach überprüfen und fortsetzen. \n\n\nFalls du experimentierfreudig bist, besteht die Möglichkeit, ein nicht\ninteraktives Rebase mit `git rebase --autosquash` durchzuführen. Dies sollte\njedoch mit Vorsicht geschehen, da du keine Möglichkeit hast, die Squashs vor\nihrer Anwendung zu überprüfen, was potenziell zu unerwarteten Ergebnissen\nführen kann.\n\n\n## Situation 4: Der Verlauf meiner Git-Commits ergibt keinen Sinn, ich\nmöchte von vorn beginnen!\n\n\nWenn wir an einer umfangreichen Funktion arbeiten, ist es üblich, dass wir\nmehrere Korrekturen und Rückmeldungen vornehmen, die häufig übertragen\nwerden. Anstatt den Branch ständig zu ändern, können wir das Aufräumen der\nGit-Commits bis zum Ende der Entwicklung aufschieben.\n\n\nIn solchen Fällen erweisen sich Patch-Dateien als äußerst praktisch. Bevor\nGit-basierte Dienste wie GitLab den Entwickler(inne)n zur Verfügung standen,\nwaren Patch-Dateien die wichtigste Methode, um bei der Zusammenarbeit an\ngroßen Open-Source-Projekten Code per E-Mail auszutauschen.\n\n\nAngenommen, du hast einen solchen Branch (z. B. \"`add-page-navigation`\"), in\ndem es tonnenweise Commits gibt, die die zugrunde liegenden Änderungen nicht\nklar vermitteln, dann kannst du folgendermaßen eine Patch-Datei für alle\nÄnderungen erstellen, die du in diesem Branch vorgenommen hast:\n\n\n- Um eine Patch-Datei zu erstellen, muss zunächst sichergestellt werden,\ndass der Branch alle Änderungen aus dem `master`-Branch enthält und keine\nKonflikte damit aufweist.\n\n- Um alle Änderungen vom Master-Branch in deinen\n`add-page-navigation`-Branch zu übernehmen, kannst du entweder `git rebase\nmaster` oder `git merge master` ausführen, während du im\n`add-page-navigation-Branch` ausgecheckt bist.\n\n- Nun erstellst du die Patch-Datei. Führe `git diff master\nadd-page-navigation > ~/add_page_navigation.patch` aus.\n  - __Aufschlüsselung des Befehls:__ Hier verwenden wir die Diff-Funktion von Git und fordern einen Vergleich zwischen dem `master`-Branch und dem `add-page-navigation`-Branch an. Die Ausgabe wird über das \"`>`\"-Symbol in eine Datei namens `add_page_navigation.patch` in unserem Benutzerverzeichnis (typischerweise ~/ in Unix-basierten Betriebssystemen) umgeleitet.\n  - Du kannst einen beliebigen Pfad angeben, in dem die Datei gespeichert werden soll. Der Dateiname und die Erweiterung können beliebig gewählt werden.\n  - Sobald der Befehl ausgeführt wurde und keine Fehler angezeigt werden, wird die Patch-Datei erstellt.\n  - Checke jetzt den `master`-Branch aus; führe `git checkout master` aus.\n  - Du kannst den Branch `add-page-navigation` aus deinem lokalen Repository löschen, indem du `git branch -D add-page-navigation` ausführst. Denke daran, dass die Änderungen dieses Branchs bereits in einer erstellten Patch-Datei enthalten sind.\n  - Erstelle nun einen neuen Branch mit demselben Namen (während `master` ausgecheckt ist); führe `git checkout -b add-page-navigation` aus.\n  - Zu diesem Zeitpunkt ist dies ein neuer Branch, der noch keine der Änderungen enthält.\n  - Zum Schluss werden die Änderungen aus der Patch-Datei übernommen; `git apply ~/add_page_navigation.patch`.\n  - Hier werden alle Änderungen in einen Branch übernommen und erscheinen als \"uncommitted\", so, als ob du alle Änderungen vorgenommen hättest, aber keine der Änderungen tatsächlich in den Branch übernommen wurden.\n  - Jetzt kannst du einzelne Dateien oder nach Einflussbereich gruppierte Dateien in der gewünschten Reihenfolge mit prägnanten Commit-Nachrichten übertragen.\n\nWie in vorherigen Situationen wurde der gesamte Branch geändert, also ist es\nan der Zeit, einen Push zu erzwingen!\n\n\n## Gründe, deine Git-Commit-Historie aufzuräumen\n\n\nBasierend auf den beschriebenen Situationen, gibt es sechs wichtige Gründe,\ndeine Git-Commit-Historie aufzuräumen:\n\n\n- __Bessere Nachvollziehbarkeit:__ Eine übersichtliche Commit-Historie\nerleichtert es Entwickler(innen)n, den [Verlauf des\nCodes](https://about.gitlab.com/de-de/solutions/source-code-management/\n\"Verlauf des Codes\") zu verstehen und Änderungen nachzuvollziehen.\n\n- __Effiziente Fehlerbehebung:__ Durch klare Commit-Nachrichten und eine\nstrukturierte Historie können Fehler schneller identifiziert und behoben\nwerden.\n\n- __Verbesserte Zusammenarbeit:__ Ein aufgeräumter Commit-Verlauf\nerleichtert die Zusammenarbeit im Team, da Entwickler(innen)schnell den\nKontext und den Zweck früherer Änderungen verstehen können.\n\n- __Effizientere Wartung:__ Weniger Zeit wird mit der Suche nach\nspezifischen Änderungen und deren Kontext verschwendet, was die Wartung des\nCodes effizienter macht.\n\n- __Verbesserte Codequalität:__ Eine saubere Commit-Historie fördert\nbewusstere Entscheidungen beim Committen und trägt so zur Verbesserung der\nCodequalität bei.\n\n- __Gesamtproduktivität steigern:__ Indem Entwickler(innen) weniger Zeit mit\nder Suche nach Informationen in der Commit-Historie verbringen, können sie\nsich besser auf die eigentliche Entwicklung konzentrieren und die\nGesamtproduktivität des Teams steigern.\n\n\nWenn du dich mit den Tipps vertraut gemacht hast, kannst du in der\n[offiziellen\nGit-Dokumentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History\n\"offiziellen Git-Dokumentation\") mehr über fortgeschrittene Konzepte zu\ndiesem Thema erfahren. Viel Spaß mit Git!\n",[9,793],"workflow","2024-10-10",{"slug":796,"featured":6,"template":685},"keeping-git-commit-history-clean","content:de-de:blog:keeping-git-commit-history-clean.yml","Keeping Git Commit History Clean","de-de/blog/keeping-git-commit-history-clean.yml","de-de/blog/keeping-git-commit-history-clean",{"_path":802,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":803,"content":806,"config":815,"_id":817,"_type":13,"title":818,"_source":15,"_file":819,"_stem":820,"_extension":18},"/de-de/blog/supercharge-your-git-workflows",{"title":804,"description":805},"Git-Workflows systematisch optimieren","Git clone-Operationen optimieren – bis zu 93% weniger Clone-Zeit und 98% weniger Speicherplatzbedarf mit dem Git Much Faster Script.",{"title":804,"description":807,"authors":808,"heroImage":810,"date":811,"category":770,"tags":812,"body":814},"Git clone-Operationen optimieren – bis zu 93 % weniger Clone-Zeit und 98 % weniger Speicherplatzbedarf.",[809],"Darwin Sanoy","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098264/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_519147119_2RafH61mqosMZv8HGAlsUj_1750098264407.jpg","2025-09-10",[729,9,813],"performance","**7 Minuten Lesezeit**\n\n\n## Der Geschäftsfall: Was Git-Performance kostet\n\n\nStellen wir uns vor: Arbeit am Chromium-Projekt, das Repository muss geklont werden. `git clone` starten, einen Kaffee holen, E-Mails checken, vielleicht eine Mittagspause – und 95 Minuten später ist endlich das Arbeitsverzeichnis da. Das ist die Realität für Entwickler, die mit großen Repositories von 50 GB+ arbeiten.\n\n\nDie Produktivitätsauswirkungen sind erheblich: CI/CD-Pipelines kommen zum Erliegen während sie auf Repository-Klone warten. Infrastrukturkosten steigen, da Compute-Ressourcen untätig bleiben. Entwickler-Frustration wächst, während Context-Switching zur Norm wird. Das Problem zeigt sich überall: Embedded-Teams erben Repositories mit Legacy-Firmware und Vendor-SDKs. Web-Anwendungen akkumulieren Marketing-Assets. Game-Development-Projekte enthalten 3D-Modelle und Audio-Dateien – Repository-Größen erreichen Dutzende von Gigabytes.\n\n\nEnterprise-CI/CD-Pipelines leiden besonders: Jeder Job braucht frische Repository-Klone. Bei 20-90 Minuten Operationszeit erliegen ganze Entwicklungsworkflows. Infrastrukturkosten steigen durch untätige Compute-Ressourcen.\n\n\n## 8-60x schneller – je nach Repository-Größe:\n\n\n[Git Much Faster](https://gitlab.com/gitlab-accelerates-embedded/misc/git-much-faster) demonstriert dramatische Verbesserungen durch rigoroses Benchmarking über reale Repositories mit konsistenter AWS-Infrastruktur:\n\n\n**Linux-Kernel-Repository (7,5 GB total):** Standard clone dauerte 6 Minuten 29 Sekunden. Optimized clone erreichte 46,28 Sekunden – eine 88,1%ige Verbesserung, wodurch das .git-Verzeichnis von 5,9 GB auf 284 MB reduziert wurde.\n\n\n**Chromium-Repository (60,9 GB total):** Standard clone benötigte 95 Minuten 12 Sekunden. Optimized clone erreichte 6 Minuten 41 Sekunden – eine beeindruckende 93%ige Verbesserung, wodurch das .git-Verzeichnis von 55,7 GB auf 850 MB komprimiert wurde.\n\n\n**GitLab-Website-Repository (8,9 GB total):** Standard clone dauerte 6 Minuten 23 Sekunden. Optimized clone erreichte 6,49 Sekunden – eine bemerkenswerte 98,3%ige Verbesserung, wodurch das .git-Verzeichnis auf 37 MB reduziert wurde.\n\n\nDie Benchmark-Daten zeigen klare Muster: Größere Repositories zeigen dramatischere Verbesserungen, binär-lastige Repositories profitieren am meisten von intelligenten Filtern, und optimierte Ansätze übertreffen konsistent sowohl standard Git als auch Gits eigenes Scalar-Tool.\n\n\n## Kosteneinsparungen für die gesamte Infrastruktur\n\n\nGit clone-Optimierung reduziert auch die Systembelastung durch kleinere Anfragegrößen. GitLabs [Gitaly Cluster](https://docs.gitlab.com/administration/gitaly/praefect/) profitiert direkt: Weniger server-seitige \"pack file\"-Erstellung bedeutet niedrigere Memory-, CPU- und I/O-Anforderungen. Der gesamte Stack wird schneller und günstiger.\n\n\nDiese Infrastructure-Einsparungen multiplizieren sich in Enterprise-Umgebungen: Reduzierte Dimensionierung der Git-Server, weniger Netzwerk-Overhead, optimierte Storage-Nutzung. Alle Schichten profitieren gleichzeitig.\n\n\n## Typische Enterprise-Anwendungsfälle\n\n\n**Embedded Development:** Legacy-Firmware, FPGA-Bitstreams, PCB-Layouts treiben Repository-Größen hoch. Build-Prozesse klonen oft Dutzende externe Repositories, multiplizieren die Performance-Auswirkungen.\n\n\n**Enterprise-Monorepos:** Mehrere Projekte, akkumulierte Historie. Media-Assets verstärken das Problem – Web-Apps mit Marketing-Assets, Games mit 3D-Modellen über 100 GB.\n\n\n**CI/CD-Pipelines:** Jeder Job braucht frische Klone. Bei 20-90 Minuten werden Workflows unbrauchbar. Hier zeigen sich die größten Produktivitätsgewinne.\n\n\n**Verteilte Teams:** Limitierte Netzwerk-Performance zu Development-Workstations profitiert von reduzierten Over-the-Wire-Größen.\n\n\n- - -\n\n\n## Die technische Umsetzung: Wie es funktioniert\n\n\nGit Much Faster ist ein Script, das ich als Enablement-Tool entwickelt habe, um verschiedene Clone-Optimierungsansätze auf demselben Client zu benchmarken – ob Entwickler-Workstation, CI, Cloud-Umgebungen oder GitOps-Klone. Es enthält kuratierte Konfigurationen für schnellste Clone-Optimierung, die sich als Ausgangspunkt nutzen lassen.\n\n\nDie Lösung adressiert die grundlegende Herausforderung: Gits Standard-Clone-Verhalten priorisiert Sicherheit über Geschwindigkeit. Bei großen Codebasen, Binär-Assets oder Monorepo-Strukturen wird das zum erheblichen Engpass.\n\n\n## Vier Benchmark-Strategien im Vergleich\n\n\nGit Much Faster löst dies durch umfassendes Benchmarking, das vier verschiedene Strategien vergleicht: standard git clone (Baseline mit vollständiger Historie), optimized git clone (custom Konfigurationen mit deaktivierter Kompression und sparse checkout), Gits Scalar clone (integriertes partial cloning) und current directory assessment (Analyse bestehender Repositories ohne erneutes Klonen).\n\n\nDas Tool bietet messbare, wiederholbare Benchmarks in kontrollierten AWS-Umgebungen. Die wahre Stärke: alle Benchmarks lassen sich in der spezifischen Umgebung ausführen – auch bei langsamen Netzwerkverbindungen findet sich die optimale Clone-Strategie.\n\n\n## Zwei Schlüssel-Konfigurationen für 93% Zeitersparnis\n\n\nDie bedeutendsten Gewinne stammen aus zwei Optimierungen:\n\n\n**Erste Optimierung – `core.compression=0`:** Eliminiert CPU-intensive Kompression während Netzwerkoperationen. Bei modernen Hochgeschwindigkeitsnetzwerken überschreiten CPU-Zyklen oft die Bandbreiteneinsparungen. Allein diese Optimierung reduziert Clone-Zeiten um 40%–60%.\n\n\n**Zweite Optimierung – `http.postBuffer=1024M`:** Erhöht Gits konservative HTTP-Buffer-Größe. Große Repositories profitieren enorm – Git kann größere Operationen handhaben ohne Aufteilen in mehrere Requests.\n\n\nZusätzlich nutzt Git Much Faster shallow clones (`--depth=1`) und partial clones (`--filter=blob:none`). Shallow clones reduzieren Daten um 70%–90%, partial clones helfen bei Repositories mit großen Binär-Assets. Sparse checkout kontrolliert ausgecheckte Dateien chirurgisch präzise – 30+ Binärdateitypen werden ausgeschlossen, Working-Directory-Größe sinkt um 78%.\n\n\nGits Scalar-Tool kombiniert partial clone, sparse checkout und Background-Wartung. Tests zeigen jedoch: Der custom optimized approach übertrifft Scalar um 48%–67% bei ähnlichen Disk-Space-Einsparungen.\n\n\n## Sofortige Implementierung in drei Schritten\n\n\nDie Implementierung erfordert das Verständnis, wann welche Technik basierend auf Use Case und Risikotoleranz anzuwenden ist. Für Development, das vollständigen Repository-Zugang erfordert: standard Git cloning nutzen. Für read-heavy Workflows, die schnellen Zugang zu aktuellem Code benötigen: optimized cloning einsetzen. Für CI/CD-Pipelines, wo Geschwindigkeit paramount ist: optimized cloning bietet maximalen Nutzen.\n\n\nDer Einstieg erfordert nur einfachen Download und Ausführung:\n\n\n```bash\n\ncurl -L https://gitlab.com/gitlab-accelerates-embedded/misc/git-much-faster/-/raw/master/git-much-faster.sh -o ./git-much-faster.sh\n\n\n\n# Für Benchmarking\n\n\nbash ./git-much-faster.sh --methods=optimized,standard --repo=https://github.com/your-org/your-repo.git\n\n```\n\n\nFür production-grade Testing enthält das Git Much Faster-Projekt komplette Terraform-Infrastruktur für AWS-Deployment, wodurch sich Variablen eliminieren lassen, die lokale Testergebnisse verzerren.\n\n\n## Wichtige Einschränkungen beachten\n\n\nOptimized clones haben Limitierungen: Shallow clones verhindern Zugang zu historischen Commits. Lösung: Entwickler starten optimized, konvertieren bei Bedarf via `git fetch --unshallow` zu full clones. CI-Jobs mit Commit-Historie-Zugriff brauchen möglicherweise vollständige Historie.\n\n\n- - -\n\n\n## Transformative Ergebnisse für deutsche Teams\n\n\nGit clone-Optimierung liefert messbare Verbesserungen – bis zu 93% weniger Clone-Zeit, 98% weniger Disk-Space-Usage. Gits konservativer Standard-Ansatz lässt erhebliche Performance-Gelegenheiten ungenutzt.\n\n\n**Für deutsche Entwicklungsteams:** Reduzierte CI/CD-Wartezeiten steigern tägliche Produktivität, geringere Infrastrukturkosten ermöglichen relevante Kosteneinsparungen in Enterprise-Umgebungen.\n\n\n[Einfach starten mit dem Git Much Faster Repository](https://gitlab.com/gitlab-accelerates-embedded/misc/git-much-faster) – read-only Optimierung in CI/CD-Pipelines beginnen, schrittweise auf Development-Workflows erweitern basierend auf gemessenen Ergebnissen.\n",{"slug":816,"template":685},"supercharge-your-git-workflows","content:de-de:blog:supercharge-your-git-workflows.yml","Supercharge Your Git Workflows","de-de/blog/supercharge-your-git-workflows.yml","de-de/blog/supercharge-your-git-workflows",{"_path":822,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":823,"content":829,"config":838,"_id":840,"_type":13,"title":841,"_source":15,"_file":842,"_stem":843,"_extension":18},"/de-de/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality",{"ogTitle":824,"schema":825,"ogImage":826,"ogDescription":827,"ogSiteName":671,"noIndex":6,"ogType":672,"ogUrl":828,"title":824,"canonicalUrls":828,"description":827},"Was ist Git? | Einfach erklärt | Praxis-Tutorial","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Was ist Git? Der ultimative Leitfaden zur Rolle und Funktionalität von Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-11-14\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673991/Blog/Hero%20Images/Git.jpg","Wir zeigen dir, was hinter Git steckt und wie du das Tool optimal nutzt. ✓ Definition ✓ Bedeutung ✓ Funktionen ✓ Vorteile ✓ Befehle ➤ Jetzt Leitfaden lesen!","https://about.gitlab.com/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality",{"heroImage":826,"body":830,"authors":831,"updatedDate":832,"date":833,"title":834,"tags":835,"description":837,"category":679},"Git ist ein unverzichtbares Tool in der modernen Softwareentwicklung. In diesem umfassenden Leitfaden erklären wir detailliert, was das Git-Tool ist, welche Rolle es bei der Versionsverwaltung von Quellcode spielt und wie es funktioniert. Egal, ob du Anfänger(in) oder Expert(in) bist: Dieser Leitfaden vermittelt dir ein tiefes Verständnis von Git und seinen vielen Funktionen.\n\n## Inhalt - Alles über Git\n\n- [Was ist Git?](#was-ist-git%3F)\n- [Was ist Versionskontrolle?](#was-ist-versionskontrolle%3F)\n- [Was sind die Funktionen von Git?](#was-sind-die-funktionen-von-git%3F)\n- [Visualisierung deines Projektverlaufs](#visualisierung-deines-projektverlaufs)\n- [Mehr Autonomie für Teams](#mehr-autonomie-f%C3%BCr-teams)\n- [Optimierung von Entwicklungs-Workflows](#optimierung-von-entwicklungs-workflows)\n- [Was sind die Vorteile von Git?](#was-sind-die-vorteile-von-git%3F)\n- [Was sind die Hauptbefehle von Git?](#was-sind-die-hauptbefehle-von-git%3F)\n- [Git und GitLab](#git-und-gitlab)\n- [FAQ zu Git](#faq-zu-git)\n\n## Was ist Git?\n\nGit ist ein Tool zur Versionskontrolle, das sich in der Welt der Softwareentwicklung schnell zu einem Muss entwickelt hat. Da mit Git Änderungen an Projekten genauestens verfolgt werden können, ist es ein unverzichtbares Tool für Entwickler(innen), um ihre Projekte effizient zu verwalten. Damit es für alle, die in der Softwareentwicklung weiterkommen möchten, unverzichtbar, Git zu beherrschen.\n\n### Was ist Versionskontrolle?\n\n[Versionskontrolle](https://about.gitlab.com/de-de/topics/version-control/) ermöglicht es dir, Änderungen am Quellcode einer Software zu verfolgen. Daher besteht jede gelieferte Softwareversion aus einer Reihe bestimmter Versionen jeder ihrer Komponenten und Quellcodedateien. Ein Icon wurde beispielsweise nur zwei Mal geändert, während eine Codedatei im Laufe der Zeit dutzende Änderungen durchgemacht hat.\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n## Was sind die Funktionen von Git?\n\nIn der Entwicklung ist es wichtig, Änderungen am Quellcode einer Software rigoros zu verwalten. Ohne diese kann unmöglich sichergestellt werden, dass Entwicklungsteams konsistent und zuverlässig arbeiten können. Ein fein abgestimmtes Änderungsmanagement kann es auch einfacher machen, die Ursache eines Problems zu identifizieren. Außerdem verringert es das Risiko von Konflikten und das Überschreiben von Dateien. In der Tat erleichtert und rationalisiert Git die Versionsverwaltung von Software genau zu diesem Zweck.\n\nUm Git und seine Funktionsweise besser zu verstehen, haben wir hier einige Hauptfunktionen angeführt, mit denen die Quellcodeverwaltung sowie de Zusammenarbeit zwischen Teams auf einfache Weise optimiert werden kann.\n\n### Visualisierung deines Projektverlaufs\n\nIn der Welt der Softwareentwicklung ist der [Commit-Verlauf](https://about.gitlab.com/blog/keeping-git-commit-history-clean/) ein Grundpfeiler, um den Projektfortschritt auf Git zu verfolgen. Daher bietet Git Entwickler(inne)n einen detaillierten Gesamtverlauf aller Änderungen am Quellcode.\n\nFür jeden neuen Commit wird Folgendes erfasst:\n\n* Spezifische Änderungen an Projektdateien\n* Eine erläuternde Nachricht des Entwicklerteams, das die Änderung vorgenommen hat\n\nDiese Elemente tragen dazu bei, die Kommunikation und den Auftrag des Entwicklungsteams zu verbessern, sodass es die Einzelheiten jeder Codeänderung schneller verstehen kann.\n\nMit diesem Verlauf kannst du nicht nur die Entwicklung des Projekts überwachen, sondern auch zurückgehen und Teile der Änderung rückgängig machen oder auch nur einen Teil der Änderungen von einem Branch zu einem anderen übertragen. Diese Funktion ist daher entscheidend, um die Transparenz, Konsistenz und Qualität des Quellcodes eines Projekts in Git zu wahren. Außerdem wird dadurch die Zusammenarbeit im Entwicklungsteam gefördert und die betriebliche Effizienz bei der Problembehebung gesteigert.\n\nSieh dir in unserem Tutorial an, [wie du deinen ersten Git-Commit erstellst](https://docs.gitlab.com/ee/tutorials/make_first_git_commit/).\n\n### Mehr Autonomie für Teams\n\nEin weiteres wesentliches Merkmal des Git-Tools ist die [verteilte Entwicklung](https://git-scm.com/about/distributed). Dank seiner dezentralen Struktur ermöglicht es Git den Teams, gleichzeitig am selben Projekt zu arbeiten. Jedes Teammitglied hat seine eigene Kopie des Projekts, in der Änderungen versioniert werden können. Dadurch können sie autonom an bestimmten Funktionen arbeiten, ohne dass es zu Konflikten oder Überschreibungen kommt. Dieser Ansatz bietet den Entwickler(inne)n große Flexibilität, denn so können sie verschiedene Ideen ausarbeiten oder mit neuen Funktionen experimentieren, ohne die Arbeit ihrer Kolleg(inn)en zu stören.\n\nDie verteilte Entwicklung verbessert auch die Resilienz gegenüber Serverausfällen. So hat jede Person im Falle eine Ausfalls eine Kopie, mit der sie offline weiterarbeiten kann. Die Änderungen können dann synchronisiert werden, sobald der Server wieder verfügbar ist. Dadurch wird verhindert, dass die Arbeit des Entwicklungsteams unterbrochen wird und es zu Einschränkungen der Betriebsteams kommt.\n\n### Optimierung von Entwicklungs-Workflows\n\nEine der leistungsstärksten Funktionen von Git ist die Möglichkeit, [Branches und ihre Zusammenführer zu verwalten (Branching und Zusammenführen)](https://git-scm.com/about/branching-and-merging). Dadurch können Teams parallel auf kooperative und organisierte Weise arbeiten. Jede neue Ergänzung am Code und jeder Bugfix kann unabhängig getestet und entwickelt werden, um sicherzustellen, dass er zuverlässig ist. Die Entwickler(innen) können die Änderungen dann einfach in den Haupt-Branch des Projekts zusammenführen.\n\nDurch diesen Ansatz können Teams die Entwicklung des Codes nachverfolgen, einfach und effizient zusammenarbeiten, Konflikte zwischen verschiedenen Versionen reduzieren und die kontinuierliche Integration der entwickelten Funktionen sicherstellen.\n\nMit diesen beiden Funktionen können Teams kontinuierlich und im Sinne der Agile-Methodik Projekte entwickeln und regelmäßig neue Codeversionen bereitstellen. Diese Vorgehensweise erleichtert das Change Management deutlich und senkt gleichzeitig das Fehlerrisiko.\n\n## Was sind die Vorteile von Git?\n\nUm Git wirklich zu verstehen, musst du all die Vorteile kennen, die es deinen Entwicklungsteams bietet:\n\n* **Dezentralisierte Versionsverwaltung:** Mit Git haben alle Entwickler(innen) eine vollständige Kopie des Projektverlaufs und können dadurch unabhängig arbeiten.\n* **Ein Tool für Sicherheit:** Anders als andere Tools zur Versionskontrolle wurde Git mit dem Gedanken entwickelt, die Integrität aller Elemente im Repository mit einem kryptografischen Secure Hash Algorithm (aktuell SHA1 und [SHA-256](https://about.gitlab.com/blog/gitlab-now-supports-sha256-repositories/)) sicherzustellen. Dieser Algorithmus soll den Code und den Verlauf des Projekts vor Änderungen – egal, ob böswillig oder nicht – schützen. Darüber hinaus kann jeder Commit (also jede Erstellung einer neuen Version) automatisch signiert werden (GPG), um die Nachvollziehbarkeit zu gewährleisten. Dies macht Git zu einem besonders sicheren Tool, das die Integrität und Authentizität deines Quellcodes und seines Verlaufs sicherstellt.\n* **Ein schnelles und effektives Tool:** Das Git-Tool wurde entwickelt, um die Effizienz bei der Entwicklung zu maximieren. Dank seiner Geschwindigkeit können Entwickler(innen) komplexe Vorgänge wie Commits, Branching und das Zusammenführen äußerst rasch durchführen, und das sogar in großen Codebases. Es sorgt auch für einen minimalen Fingerabdruck auf der Festplatte und beim Netzwerkaustausch. Diese Effizienz führt zu kürzeren Reaktionszeiten bei Backups, Beratungen und Änderungen am Projektverlauf.\n* **Mehr Flexibilität beim Arbeiten:** Git unterstützt eine Vielzahl an Entwicklungs-Workflows. Egal, ob du zentralisierte Entwicklungsmodelle oder eher einen linearen Ansatz bevorzugst: Git lässt sich einfach anpassen. Diese Fähigkeit, verschiedene Workflows zu verwalten, bietet Teams zahlreiche Optionen für ihre Arbeitsweise.\n* **Einfache Integration:** Git zeichnet sich dadurch aus, dass es sich in eine ganze Reihe bestehender Entwicklungstools und -plattformen integrieren lässt. Durch diese breite Kompatibilität können Teams die besten DevSecOps-Tools und -Praktiken nutzen und dadurch ihre Projekte effizienter verwalten.\n* **Ein weithin anerkanntes Open-Source-Projekt:** Ein weiterer bedeutender Vorteil von Git ist, dass es ein Open-Source-Projekt ist und von einer dynamischen, engagierten Community unterstützt wird, wodurch die kontinuierliche Weiterentwicklung sichergestellt wird. Durch diese aktive Beteiligung von Einzelpersonen und Unternehmen in der Git-Community kommen im Rahmen kontinuierlicher Updates regelmäßig neue Funktionen und Verbesserungen hinzu.\n\n## Was sind die Hauptbefehle von Git?\n\nDas Open-Source-Projekt Git bietet eine Vielzahl an Befehlen, um die Teamarbeit zu erleichtern.  \nHier sind einige der am häufigsten verwendeten Befehle.\n\n* **git init:** Ein neues Git-Repository initialisieren.  \n* **git clone \\[url\\]:** Ein vorhandenes Repository klonen.  \n* **git add \\[file\\]:** Eine Datei zum Index hinzufügen.  \n* **git commit:** Die vorgenommenen Änderungen validieren.  \n* **git commit \\-m \"message\":** Änderungen mit einer Nachricht validieren.  \n* **Git-Status:** Den Status der Dateien im Arbeitsverzeichnis anzeigen.  \n* **git push:** Änderungen an das Remote-Repository senden.  \n* **git pull:** Änderungen aus dem Remote-Repository abrufen und sie mit dem lokalen Repository zusammenführen. Alles über git pull erfährst du in diesem umfangreichen Artikel [git fetch vs. git pull](https://about.gitlab.com/de-de/blog/git-pull-vs-git-fetch-whats-the-difference/).\n\nDiese Befehle sind zwar unerlässlich, um mit Git loszulegen – es gibt aber noch viele andere Befehle. Du findest sie in der [Liste der Git-Befehle](https://git-scm.com/docs).\n\n## Git und GitLab\n\nGitLab ist eine kollaborative Open-Source-Entwicklungsplattform, die alle Phasen des DevSecOps-Lebenszyklus abdeckt und einen Git-Server für eine effiziente Teamzusammenarbeit bietet.\n\nNeben der Quellcodeverwaltung bietet GitLab ein umfassendes Programmpaket für kontinuierliche Integration und Verteilung, Verwaltung von Ergebnissen, Sicherheits- und Vorfallmanagement sowie Nachvollziehbarkeit, Aufgabenplanung und -nachverfolgung in Echtzeit, Bereitstellungsüberwachung, Software-Versionsverwaltung und die zugehörigen Dokumente.\n## FAQ zu Git\n\n### Warum sollte man Git verwenden?\n\nBei Git dreht sich alles um Effizienz. Durch das dezentrale System von Git, das auf Branching und Funktionen zum Zusammenführen basiert, können Entwicklungsteams am selben Projekt arbeiten, ohne sich gegenseitig zu stören und (was noch wichtiger ist) ohne Versionskonflikte zu erschaffen.\n\n### Ist Git Software?\n\nGit ist ein Open-Source-Projekt. Daher ist es kostenlos und für alle offen. Du musst jedoch [Git](https://docs.gitlab.com/ee/topics/git/how_to_install_git/) auf deinem Gerät installieren, bevor du mit der Arbeit beginnen kannst.\n\n### Was ist ein Branch in Git?\n\nIn Git ist ein Branch ein Zeiger auf einen Änderungsverlauf. Somit verweist jeder Haupt-Branch auf den letzten Commit, der auf ihm ausgeführt wurde. Es ist daher möglich, viele parallele Branches zu haben, die alle ihren eigenen Verlauf, jedoch die gleiche Wurzel haben.\n\n### Was ist ein Commit?\n\nIn Git ist ein Commit ein Datensatz von Änderungen am Quellcode einer Software. Jeder Commit wird von einer erläuternden Nachricht begleitet, die den Gesamtverlauf aller Änderungen dokumentiert. Dies erleichtert die Nachverfolgung von Projekten. Außerdem gibt es immer die Möglichkeit, bei Problemen zu früheren, funktionierenden Versionen zurückzukehren.\n\n### Was sind die Vorteile von Branches in Git?\n\nDurch die Entwicklung von Funktionen in Branches können Entwickler(innen) gleichzeitig an mehreren unterschiedlichen Funktionen arbeiten. Darüber hinaus wird dadurch vermieden, dass der Haupt-Branch mit instabilem Code kompromittiert wird. Außerdem ist die Implementierung von Branches in Git deutlich leichter als in anderen Versionskontrollsystemen.",[702],"2025-07-10","2024-11-14","Was ist Git? Der ultimative Leitfaden",[9,836,681],"DevSecOps","Möchtest du deine Projekte mit Git umsetzen? Entdecke alle Vorteile und Funktionen von Git in unserem umfassenden Guide.",{"slug":839,"featured":6,"template":685},"what-is-git-the-ultimate-guide-to-gits-role-and-functionality","content:de-de:blog:what-is-git-the-ultimate-guide-to-gits-role-and-functionality.yml","What Is Git The Ultimate Guide To Gits Role And Functionality","de-de/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality.yml","de-de/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality",{"_path":845,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":846,"content":852,"config":860,"_id":862,"_type":13,"title":863,"_source":15,"_file":864,"_stem":865,"_extension":18},"/de-de/blog/what-is-gitflow",{"ogTitle":847,"schema":848,"ogImage":849,"ogDescription":850,"ogSiteName":671,"noIndex":6,"ogType":672,"ogUrl":851,"title":847,"canonicalUrls":851,"description":850},"Was ist GitFlow? Ein Leitfaden inkl. Beispiel","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Was ist GitFlow?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Team\"}],\n        \"datePublished\": \"2024-09-27\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659838/Blog/Hero%20Images/AdobeStock_662057734.jpg","Wir zeigen dir, was sich hinter GitFlow verbirgt. ✓ Definition ✓ Funktionsweise ✓ GitFlow vs. GitLab Flow ✓ Vorteile ✓ Beispiel ➤ Jetzt Leitfaden lesen!","https://about.gitlab.com/blog/what-is-gitflow",{"heroImage":849,"body":853,"authors":854,"updatedDate":856,"date":857,"title":847,"tags":858,"description":859,"category":679},"In GitFlow erstellen Entwickler(innen) zusätzlich zum „`main`“-Branch (Produktionszweig) einen separaten „`develop`“-Branch und legen diesen als Standard fest. In [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) kannst du jedoch sofort mit der Arbeit am `main`\\-Branch beginnen. [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) enthält einen Vorproduktionsbranch, `main`. Du kannst Änderungen in einen Branch zusammenführen und Fehler beheben, bevor du mit der Produktion beginnst. Teams können beliebig viele Vorproduktionsbranches hinzufügen: z. B. von `main` zum Test, vom Test zur Genehmigung oder von der Genehmigung zur Produktion. \n\nHier erklären wir klar und deutlich die Unterschiede zwischen GitFlow und [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/), was GitFlow ist, wie GitFlow funktioniert, welche Vorteile seine Verwendung bietet und beantworten häufig gestellte Fragen. \n\n## Inhaltsverzeichnis\n\n- [Was ist GitFlow?](#was-ist-gitflow%3F)\n- [So funktioniert GitFlow](#so-funktioniert-gitflow)\n- [Was ist der Unterschied zwischen GitFlow und GitLab Flow?](#was-ist-der-unterschied-zwischen-gitflow-und-gitlab-flow%3F)\n  - [GitFlow-Workflow](#gitflow-workflow)\n  - [GitLab-Flow-Workflow](#gitlab-flow-workflow)\n- [Vorteile der Verwendung und Funktionen von GitFlow](#vorteile-der-verwendung-und-funktionen-von-gitflow)\n  - [Vorteil 1: Fehlerbehebungen werden schneller verarbeitet](#vorteil-1-fehlerbehebungen-werden-schneller-verarbeitet)\n  - [Vorteil 2: Garantierte Tests](#vorteil-2-garantierte-tests)\n  - [Vorteil 3: Rationalisierung des Softwareentwicklungsprozesses](#vorteil-3-rationalisierung-des-softwareentwicklungsprozesses)\n  - [Vorteil 4: Effektivere Zusammenarbeit, Konfliktlösung und kontinuierliche Lieferung](#vorteil-4-effektivere-zusammenarbeit-konfliktlösung-und-kontinuierliche-lieferung)\n- [GitFlow-Beispiel](#gitflow-beispiel)\n- [GitLab-Flow- und GitFlow-FAQs (häufig gestellte Fragen)](#gitlab-flow--und-gitflow-faqs-(häufig-gestellte-fragen))\n  - [F: Was ist Git Feature Flow?](#f-was-ist-git-feature-flow%3F)\n  - [F: Lohnt es sich, GitLab Flow zu verwenden?](#f-lohnt-es-sich-gitlab-flow-zu-verwenden%3F)\n  - [F: Welche Option passt besser für mich: GitLab Flow oder GitFlow?](#f-welche-option-passt-besser-für-mich-gitlab-flow-oder-gitflow%3F)\n- [Verwandte Artikel](#verwandte-artikel)\n- [Beginne noch heute mit GitLab](#beginne-noch-heute-mit-gitlab)\n\n## Was ist GitFlow?\n\nGitFlow ist ein Git-Workflow, der Git-Braches (verteiltes Versionskontrollsystem) verwaltet und ein Branchingmodell eines Repositorys in Git. Es wurde entwickelt, um die Komplexität des Software-Release-Managements zu vereinfachen und wurde erstmals im Jahr 2010 von Vincent Driessen verwendet. Besonders größere Teams finden es hilfreich. \n\n## So funktioniert GitFlow\n\nIm Vergleich zur Trunk-basierten Entwicklung verfügt GitFlow über persistente Branches und große Commits. GitFlow kann für Projekte mit festen Release-Zyklen und für bewährte [DevOps](https://about.gitlab.com/de-de/solutions/devops-platform/)\\-Methoden für die kontinuierliche Bereitstellung verwendet werden. GitFlow verfügt über einen strukturierten Workflow, sodass du deine Branches definieren kannst, indem du beispielsweise Feature-Branches zu deinen Entwicklungs- und Hauptbranches hinzufügst, dann einen Release-Branch hinzufügst usw. Dadurch wird es für dein Team einfacher, die Struktur zu verstehen und zu erkennen, wo in der Entwicklungspipeline Änderungen vorgenommen werden müssen. \n\n## Was ist der Unterschied zwischen GitFlow und GitLab Flow?\n\nGitFlow ist ein Branchingmodell für Git, das zusätzlich zu Feature-Branches mehrere main-Branches verwendet. [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) löst die Probleme, die GitFlow hatte, und ermöglicht Teammitgliedern, effizienter zu arbeiten. Sehen wir uns die Unterschiede im Workflow im Detail an. \n\n### GitFlow-Workflow\n\nDer GitFlow-Workflow hat fünf Branches: \n\n1. main\u003Cbr>\n2. develop\u003Cbr>\n3. feature\u003Cbr>\n4. release\u003Cbr>\n5. hotfix\u003Cbr>\n\nWenn du GitFlow zur Code-Entwicklung verwendest, hast du einen main-Branch und alle unterstützenden Branches. Der main-Branch hat zwei Branches: den main-Branch für die Veröffentlichung des Produkts und den develop-Branch für die Verwaltung des in Entwicklung befindlichen Quellcodes. Wir stabilisieren den Code im develop-Branch und führen ihn dann in den main-Branch zusammen, wenn er zur Veröffentlichung bereit ist. Im support-Branch erstellen wir Branches wie feature, release und hotfix und fahren mit den einzelnen Arbeiten fort. \n\n### GitLab-Flow-Workflow\n[GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) rationalisiert die Entwicklung, indem es den Aufwand für Freigabe, Markierung, Zusammenführung usw. eliminiert. \n\n[GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) ist eine vereinfachte Version von GitFlow, die funktionszentrierte Entwicklung mit Funktionen zur Problemverfolgung kombiniert. [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) macht deine Arbeit einfach, klar und effizient. [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) enthält bewährte Methoden, die Softwareentwicklungsteams dabei helfen, Funktionen reibungslos zu veröffentlichen. \n\n[GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) ist der Workflow, der in der GitLab-Entwicklung verwendet wird, und der `main`\\-Branch, ein `pre-production`, einen Branch für Tests vor der Veröffentlichung, `production`, der den veröffentlichten Code verwaltet, und `feature`/`hotfix`, der für die Entwicklung von Funktionen und die Behebung von Fehlern verwendet wird. Teams können beliebig viele Vorproduktionsbranches hinzufügen. Du kannst beispielsweise einen Ablauf von `main` zu Test, von Test zu Approval und von Approval zu Produktion erstellen. \n\nDas Team erstellt Feature-Branches und pflegt gleichzeitig den Produktionsbranch. Sobald der main-Branch zur Bereitstellung bereit ist, führst du ihn in den Produktionszweig zusammen und gibst ihn frei. [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) kann auch in Release-Branches verwendet werden. Teams, die eine öffentliche API benötigen, müssen jedoch verschiedene Versionen verwalten. Mit [GitLab Flow](https://about.gitlab.com/de-de/topics/version-control/what-is-gitlab-flow/) können Sie jedoch v1- und v2-Branches erstellen, die separat verwaltet werden können, sodass Sie zu v1 zurückkehren können, wenn Sie während der Codeüberprüfung einen Fehler finden, was sehr praktisch ist. \n\n## Vorteile der Verwendung und Funktionen von GitFlow\n### Vorteil 1: Fehlerbehebungen werden schneller verarbeitet\n\nEiner der Vorteile der Verwendung von GitFlow besteht darin, dass Fehlerbehebungen in der Produktion schnell verarbeitet werden können. GitFlow ist ein Workflow zur Verwendung von Git (einem verteilten Versionskontrollsystem) bei der Entwicklung komplexer Software in großen Teams. \n\n### Vorteil 2: Garantierte Tests\n\nWenn du Software aus einem Release-Branch veröffentlichst, kannst du einen Zeitraum festlegen, während dessen Benutzer(innen) sie in einer Staging-Umgebung testen können. Dies kann unabhängig von der Code-Entwicklung erfolgen. Und da Commits nachgelagert sind, kannst du sicher sein, dass sie in allen Umgebungen getestet wurden. \n\n### Vorteil 3: Rationalisierung des Softwareentwicklungsprozesses\n\nGitFlow hilft dir, das Beste aus Git herauszuholen. So kannst du den Softwareentwicklungsprozess optimieren. \n\n### Vorteil 4: Effektivere Zusammenarbeit, Konfliktlösung und kontinuierliche Lieferung\n\nDurch die Einführung von GitFlow kann die Zusammenarbeit effizienter gestaltet werden. Zusammenführungskonflikte können schnell gelöst werden, wodurch eine kontinuierliche Lieferung ermöglicht wird. \n\n## GitFlow-Beispiel\nDas folgende Diagramm zeigt ein Beispiel einer GitFlow-Konfiguration. Das Gesamtkonzept und die Struktur der einzelnen Branches sind sicher verständlich. \n\n![AdobeStock 569852816](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673714/Blog/Content%20Images/AdobeStock_569852816.jpg)\n\n## GitLab-Flow- und GitFlow-FAQs (häufig gestellte Fragen) \n\n### F: Was ist Git Feature Flow? \nA: Es ist einer der für die Verwendung von Git vorgeschlagen Entwicklungsabläufe. Für eine einfache Entwicklung kann Git Feature Flow verwendet werden. \n\n### F: Lohnt es sich, GitLab Flow zu verwenden? \n\nA: Ja. GitLab Flow reduziert den Aufwand für Veröffentlichung, Taggen, Zusammenführen und mehr. Dies sind Probleme, die häufig in anderen Git-Workflows auftreten. Weitere Informationen findest du [hier](https://about.gitlab.com/de-de/topics/version-control/what-are-gitlab-flow-best-practices/). \n\n### F: Welche Option passt besser für mich: GitLab Flow oder GitFlow? \n\nA: Aufgrund seiner Struktur eignet sich GitFlow besser für große Projekte mit klar getrennten Entwicklungsphasen, während GitLab Flow agiler ist und sich besser für Projekte eignet, bei denen kontinuierliche Lieferung und schnelle Releases im Vordergrund stehen. \n\n## Verwandte Artikel\n\n[Über GitLab DevSecOps](https://about.gitlab.com/de-de/)\n\n## Beginne noch heute mit GitLab\n\nWeitere Informationen zu Git und Versionskontrolle findest du [hier](https://about.gitlab.com/resources/). Möchtest du erfahren, welche Möglichkeiten eine integrierte DevSecOps-Plattform für dein Team bietet? \n\n[Kostenlose Testversion anfordern](https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com)\n",[855],"GitLab Team","2025-05-29","2024-09-27",[9,681],"Wir stellen die Unterschiede zwischen GitFlow und GitLab Flow vor, erklären, was GitFlow ist, wie GitFlow funktioniert, welche Vorteile seine Verwendung bietet (inklusive FAQ)",{"slug":861,"featured":6,"template":685},"what-is-gitflow","content:de-de:blog:what-is-gitflow.yml","What Is Gitflow","de-de/blog/what-is-gitflow.yml","de-de/blog/what-is-gitflow",{"_path":867,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":868,"content":871,"config":879,"_id":881,"_type":13,"title":882,"_source":15,"_file":883,"_stem":884,"_extension":18},"/de-de/blog/what-s-new-in-git-2-50-0",{"noIndex":6,"title":869,"description":870},"GitLab: Was gibt es Neues in Git 2.50.0?","Beiträge des Git-Teams von GitLab und der Git-Community, inklusive des Befehls git-diff-pairs(1) und der Option git-rev-list(1) für gebündelte Referenz-Updates.",{"title":872,"description":870,"authors":873,"heroImage":875,"body":876,"date":877,"category":679,"tags":878},"Was gibt es Neues in Git 2.50.0?",[874],"Justin Tobler","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663087/Blog/Hero%20Images/git3-cover.png","Das Git-Projekt hat kürzlich\n\n[Git Version 2.50.0](https://lore.kernel.org/git/xmqq1prj1umb.fsf@gitster.g/T/#u)\n\nveröffentlicht. Werfen wir einen Blick auf die Highlights dieser\n\nVeröffentlichung, die Beiträge des Git-Teams von GitLab und der gesamten\n\nGit-Community enthält.\n\n\n\n## Neuer Befehl git-diff-pairs(1)\n\n\n\nDiffs sind das Herzstück jeder Code Review und zeigen alle Änderungen, die zwischen zwei Revisionen vorgenommen wurden. GitLab zeigt Diffs an verschiedenen Stellen an, am häufigsten aber auf der [Registerkarte „Änderungen“ (in englischer Sprache verfügbar)](https://docs.gitlab.com/user/project/merge_requests/changes/) eines Merge Requests.\n\n\n\nIm Hintergrund wird die Diff-Generierung von [`git-diff(1)`](https://git-scm.com/docs/git-diff/de) verwendet. Ein Beispiel:\n\n\n\n```shell\n\n\n$ git diff HEAD~1 HEAD\n\n\n```\n\n\n\nDieser Befehl gibt das vollständige Diff für alle geänderten Dateien zurück. Dies kann eine Herausforderung für die Skalierbarkeit darstellen, vor allem, wenn die Anzahl der Dateien, die innerhalb einer Reihe von Revisionen geändert wurden, sehr groß ist. Dies kann dazu führen, dass der Befehl selbst auferlegte Zeitlimits für das GitLab-Backend erreicht. Bei großen Änderungen wäre es besser, wenn\n\n\nes eine Möglichkeit gäbe, die Diff-Berechnung in kleinere, leichter verarbeitbare Blöcke zu unterteilen.\n\n\n\nEine Möglichkeit dafür ist die Verwendung von\n\n\n[`git-diff-tree(1)` (in englischer Sprache verfügbar)](https://git-scm.com/docs/git-diff-tree), um Informationen\n\n\nüber alle geänderten Dateien abzurufen:\n\n\n\n```shell\n\n\n$ git diff-tree -r -M --abbrev HEAD~ HEAD\n\n\n:100644 100644 c9adfed339 99acf81487 M      Documentation/RelNotes/2.50.0.adoc\n\n\n:100755 100755 1047b8d11d 208e91a17f M      GIT-VERSION-GEN\n\n\n```\n\n\n\nGit bezeichnet diese Ausgabe als [„unbearbeitetes“ Format (in englischer Sprache verfügbar)](https://git-scm.com/docs/git-diff-tree#_raw_output_format).\n\n\nKurz gesagt, listet jede Zeile der Ausgabe Dateipaare und die dazugehörigen Metadaten\n\n\ndarüber auf, was sich zwischen dem Anfangscode und der letzten Revision geändert hat. Im Vergleich zur\n\n\nErzeugung der „Patch“-Ausgabe für große Änderungen verläuft dieser Prozess relativ\n\n\nschnell und liefert eine Zusammenfassung aller Änderungen. Dieser Befehl kann optional eine Umbenennungserkennung durchführen, indem das Flag `-M` angehängt wird. So kannst du überprüfen, ob identifizierte Änderungen auf eine Dateiumbenennung zurückzuführen sind.\n\n\n\nMit diesen Informationen könnten wir `git-diff(1)` verwenden, um jedes der\n\n\nDateipaar-Diffs einzeln zu erstellen. Zum Beispiel können wir die Blob-IDs\n\n\ndirekt angeben:\n\n\n\n```shell\n\n\n$ git diff 1047b8d11de767d290170979a9a20de1f5692e26 208e91a17f04558ca66bc19d73457ca64d5385f\n\n\n```\n\n\n\nWir können diesen Vorgang für jedes der Dateipaare wiederholen, aber es ist nicht sehr effizient, für jede einzelne Datei einen\n\n\nseparaten Git-Prozess zu starten.\n\n\nAußerdem verliert das Diff bei der Verwendung von Blob-IDs einige Kontextinformationen,\n\n\nwie den Änderungsstatus und die Dateimodi, die im übergeordneten\n\n\nBaumobjekt gespeichert sind. Was wir wirklich möchten, ist ein Mechanismus, um „unbearbeitete“ Dateipaarinformationen einzuspeisen und\n\n\ndie entsprechende Patch-Ausgabe zu generieren.\n\n\n\nMit der Version 2.50 bietet Git einen neuen integrierten Befehl mit der Bezeichnung\n\n\n[`git-diff-pairs(1)` (in englischer Sprache verfügbar](https://git-scm.com/docs/git-diff-pairs). Dieser Befehl\n\n\nakzeptiert „unbearbeitete“ formatierte Dateipaarinformationen als Eingabe auf stdin, um exakt zu bestimmen, welche Patches ausgegeben werden sollen. Das folgende Beispiel zeigt, wie dieser Befehl\n\n\nverwendet werden kann:\n\n\n\n```shell\n\n\n$ git diff-tree -r -z -M HEAD~ HEAD | git diff-pairs -z\n\n\n```\n\n\n\nBei dieser Nutzung ist die resultierende Ausgabe identisch mit der Verwendung von `git-diff(1)`.\n\n\nDurch einen separaten Befehl zur Generierung der Patch-Ausgabe kann die „unbearbeitete“ Ausgabe von\n\n\n`git-diff-tree(1)` in kleinere Chargen von Dateipaaren aufgeteilt und separaten\n\n\n`git-diff-pairs(1)`-Prozessen zugeführt werden. Dies löst das zuvor erwähnte\n\n\nSkalierbarkeitsproblem, da die Diffs nicht länger alle auf einmal berechnet werden müssen. Zukünftige\n\n\nGitLab-Versionen könnten auf diesem Mechanismus aufbauen, um die Leistung der\n\n\nDiff-Generierung zu verbessern, insbesondere wenn es sich um große Änderungssätze\n\n\nhandelt. Weitere Informationen zu dieser Änderung findest du im entsprechenden\n\n\n[Mailinglisten-Thread](https://lore.kernel.org/git/20250228213346.1335224-1-jltobler@gmail.com/).\n\n\n\n*Dieses Projekt wurde von [Justin Tobler](https://gitlab.com/justintobler) geleitet.*\n\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n\n## Gesammelte Referenz-Updates\n\n\n\nMit dem Git-Befehl [`git-update-ref(1)` (in englischer Sprache verfügbar)](https://git-scm.com/docs/git-update-ref)\n\n kannst du Referenzaktualisierungen durchführen. Bei Verwendung mit dem Flag `--stdin` können\n\nmehrere Referenzaktualisierungen in einer einzigen Transaktion gebündelt werden, indem Anweisungen für jede Referenzaktualisierung\n\n\nangegeben werden, die auf stdin durchgeführt werden soll.\n\n\nDie Massenaktualisierung von Referenzen auf diese Weise zeigt auch ein atomares Verhalten, bei dem ein\n\n\neinzelner Fehler bei der Referenzaktualisierung eine Transaktion abbricht und\n\n\nReferenzen nicht aktualisiert werden. Hier ist ein Beispiel für dieses Verhalten:\n\n\n\n```shell\n\n\n# Erstelle ein Repository mit drei leeren Commits und einem Branch mit dem Namen „foo“\n\n\n$ git init\n\n\n$ git commit --allow-empty -m 1\n\n\n$ git commit --allow-empty -m 2\n\n\n$ git commit --allow-empty -m 3\n\n\n$ git branch foo\n\n\n\n# Gib die Commit-IDs aus\n\n\n$ git rev-list HEAD\n\n\ncf469bdf5436ea1ded57670b5f5a0797f72f1afc\n\n\n5a74cd330f04b96ce0666af89682d4d7580c354c\n\n\n5a6b339a8ebffde8c0590553045403dbda831518\n\n\n\n# Versuche, eine neue Referenz zu erstellen und die vorhandene Referenz in der Transaktion zu aktualisieren.\n\n\n# Es wird erwartet, dass die Aktualisierung fehlschlägt, da die angegebene alte Objekt-ID nicht richtig ist.\n\n\n$ git update-ref --stdin \u003C\u003CEOF\n\n\n> create refs/heads/bar cf469bdf5436ea1ded57670b5f5a0797f72f1afc\n\n\n> update refs/heads/foo 5a6b339a8ebffde8c0590553045403dbda831518 5a74cd330f04b96ce0666af89682d4d7580c354c\n\n\n> EOF\n\n\nfatal: cannot lock ref 'refs/heads/foo': is at cf469bdf5436ea1ded57670b5f5a0797f72f1afc but expected 5a74cd330f04b96ce0666af89682d4d7580c354c\n\n\n\n# Die Referenz „bar“ wurde nicht erstellt.\n\n\n$ git switch bar\n\n\nfatal: invalid reference: bar\n\n\n```\n\n\n\nIm Vergleich zur einzelnen Aktualisierung vieler Referenzen ist die Massenaktualisierung\n\n\nauch viel effizienter. Das ist zwar grundsätzlich eine gute Lösung, aber es kann bestimmte\n\n\nUmstände geben, unter denen es akzeptabel ist, wenn ein Teil der angeforderten Referenzaktualisierungen\n\n\nfehlschlägt, wir aber dennoch die Effizienzvorteile von\n\n\nMassenaktualisierungen nutzen möchten.\n\n\n\nAb dieser Version verfügt `git-update-ref(1)` über die neue Option `--batch-updates`, mit\n\n\nder die Aktualisierungen auch dann fortgesetzt werden können, wenn eine oder mehrere Referenzaktualisierungen\n\n\nfehlschlagen. In diesem Modus werden einzelne Fehler im folgenden Format gemeldet:\n\n\n\n```text\n\n\nrejected SP (\u003Cold-oid> | \u003Cold-target>) SP (\u003Cnew-oid> | \u003Cnew-target>) SP \u003Crejection-reason> LF\n\n\n```\n\n\n\nDadurch können erfolgreiche Referenzaktualisierungen fortgesetzt werden, während gleichzeitig angegeben wird, unter welchen Umständen Aktualisierungen abgelehnt wurden und aus welchem Grund. Wir verwenden noch einmal das gleiche beispielhafte Repository wie im vorherigen Beispiel:\n\n\n\n```shell\n\n\n# Versuche, eine neue Referenz zu erstellen und die vorhandene Referenz in der Transaktion zu aktualisieren.\n\n\n$ git update-ref --stdin --batch-updates \u003C\u003CEOF\n\n\n> create refs/heads/bar cf469bdf5436ea1ded57670b5f5a0797f72f1afc\n\n\n> update refs/heads/foo 5a6b339a8ebffde8c0590553045403dbda831518 5a74cd330f04b96ce0666af89682d4d7580c354c\n\n\n> EOF\n\n\nrejected refs/heads/foo 5a6b339a8ebffde8c0590553045403dbda831518 5a74cd330f04b96ce0666af89682d4d7580c354c incorrect old value provided\n\n\n\n# Die Referenz „bar“ wurde erstellt, obwohl die Aktualisierung auf „foo“ abgelehnt wurde.\n\n\n$ git switch bar\n\n\nSwitched to branch 'bar'\n\n\n```\n\n\n\nMit der Option `--batch-updates` war die Referenzerstellung diesmal erfolgreich,\n\n\nobwohl die Aktualisierung nicht funktioniert hat. Diese Patch-Serie legt den Grundstein für\n\n\nzukünftige Leistungsverbesserungen in `git-fetch(1)` und `git-receive-pack(1)`,\n\n\nwenn Referenzen in großer Zahl aktualisiert werden. Weitere Informationen findest du im\n\n\n[Mailinglisten-Thread](https://lore.kernel.org/git/20250408085120.614893-1-karthik.188@gmail.com/)\n\n\n\n*Dieses Projekt wurde von [Karthik Nayak](https://gitlab.com/knayakgl) geleitet.*\n\n\n\n## Neue Filteroption für git-cat-file(1)\n\n\n\nMit [`git-cat-file(1)` (in englischer Sprache verfügbar)](https://git-scm.com/docs/git-cat-file) ist es möglich,\n\n\nInformationen für alle im Repository enthaltenen Objekte über die Option\n\n\n`--batch–all-objects` auszugeben. Zum Beispiel:\n\n\n\n```shell\n\n\n# Richte ein einfaches Repository ein.\n\n\n$ git init\n\n\n$ echo foo >foo\n\n\n$ git add foo\n\n\n$ git commit -m init\n\n\n\n# Erstelle ein nicht erreichbares Objekt.\n\n\n$ git commit --amend --no-edit\n\n\n\n# Verwende git-cat-file(1), um Informationen über alle Objekte einschließlich nicht erreichbarer Objekte auszugeben.\n\n\n$ git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)'\n\n\ncommit 0b07e71d14897f218f23d9a6e39605b466454ece\n\n\ntree 205f6b799e7d5c2524468ca006a0131aa57ecce7\n\n\nblob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99\n\n\ncommit c999f781fd7214b3caab82f560ffd079ddad0115\n\n\n```\n\n\n\nIn einigen Situationen möchte ein(e) Benutzer(in) möglicherweise alle Objekte im\n\n\nRepository durchsuchen, aber nur eine Teilmenge basierend auf einem bestimmten Attribut ausgeben. Wenn\n\n\nwir beispielsweise nur die Objekte anzeigen möchten, die Commits sind, könnten wir\n\n\n`grep(1)` verwenden:\n\n\n\n```shell\n\n\n$ git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)' | grep ^commit\n\n\ncommit 0b07e71d14897f218f23d9a6e39605b466454ece\n\n\ncommit c999f781fd7214b3caab82f560ffd079ddad0115\n\n\n```\n\n\n\nDas funktioniert zwar, aber ein Nachteil beim Filtern der Ausgabe ist, dass\n\n\n`git-cat-file(1)` nach wie vor alle Objekte im Repository durchlaufen muss, auch\n\n\ndiejenigen, an denen wir nicht interessiert sind. Dies kann ziemlich ineffizient sein.\n\n\n\nMit dieser Version verfügt `git-cat-file(1)` jetzt über die Option `--filter`, die nur jene Objekte\n\n\nanzeigt, die den angegebenen Kriterien entsprechen. Dies ähnelt der gleichnamigen Option\n\n\nfür `git-rev-list(1)`, unterstützt jedoch nur eine Teilmenge der\n\n\nFilter. Die folgenden Filter werden unterstützt: `blob:none`, `blob:limit=` und\n\n\n`object:type=`. Ähnlich wie im vorherigen Beispiel können Objekte mit Git direkt nach\n\n\nihrem Typ gefiltert werden:\n\n\n\n```shell\n\n\n$ git cat-file --batch-all-objects --batch-check='%(objecttype) %(objectname)' --filter='object:type=commit'\n\n\ncommit 0b07e71d14897f218f23d9a6e39605b466454ece\n\n\ncommit c999f781fd7214b3caab82f560ffd079ddad0115\n\n\n```\n\n\n\nEs ist nicht nur praktisch, dass Git die Verarbeitung übernimmt, sondern bei großen\n\n\nRepositories mit vielen Objekten ist dies möglicherweise auch effizienter. Wenn ein\n\n\nRepository über Bitmap-Indizes verfügt, kann Git Objekte eines bestimmten Typs effizient\n\n\nnachschlagen und so das Durchsuchen der\n\n\nPaketierungsdatei vermeiden, wodurch die Geschwindigkeit deutlich erhöht wird. Benchmarks, die im\n\n\n[Chromium-Repository](https://github.com/chromium/chromium.git) durchgeführt wurden, zeigen signifikante Verbesserungen:\n\n\n\n```text\n\n\nBenchmark 1: git cat-file --batch-check --batch-all-objects --unordered --buffer --no-filter Time (mean ± σ):     82.806 s ±  6.363 s    [User: 30.956 s, System: 8.264 s] Range (min … max):   73.936 s … 89.690 s    10 runs\n\n\nBenchmark 2: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tag Time (mean ± σ):      20.8 ms ±   1.3 ms    [User: 6.1 ms, System: 14.5 ms] Range (min … max):    18.2 ms …  23.6 ms    127 runs\n\n\nBenchmark 3: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=commit Time (mean ± σ):      1.551 s ±  0.008 s    [User: 1.401 s, System: 0.147 s] Range (min … max):    1.541 s …  1.566 s    10 runs\n\n\nBenchmark 4: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tree Time (mean ± σ):     11.169 s ±  0.046 s    [User: 10.076 s, System: 1.063 s] Range (min … max):   11.114 s … 11.245 s    10 runs\n\n\nBenchmark 5: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=blob Time (mean ± σ):     67.342 s ±  3.368 s    [User: 20.318 s, System: 7.787 s] Range (min … max):   62.836 s … 73.618 s    10 runs\n\n\nBenchmark 6: git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=blob:none Time (mean ± σ):     13.032 s ±  0.072 s    [User: 11.638 s, System: 1.368 s] Range (min … max):   12.960 s … 13.199 s    10 runs\n\n\nSummary git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tag 74.75 ± 4.61 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=commit 538.17 ± 33.17 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=tree 627.98 ± 38.77 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=blob:none 3244.93 ± 257.23 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --filter=object:type=blob 3990.07 ± 392.72 times faster than git cat-file --batch-check --batch-all-objects --unordered --buffer --no-filter\n\n\n```\n\n\n\nInteressanterweise zeigen diese Ergebnisse, dass die Berechnungszeit jetzt mit\n\n\nder Anzahl der Objekte für einen bestimmten Typ skaliert, anstatt mit der Anzahl der gesamten Objekte\n\n\nin der Paketierungsdatei. Den ursprünglichen (englischsprachigen) Mailinglisten-Thread findest du\n\n\n[hier](https://lore.kernel.org/git/20250221-pks-cat-file-object-type-filter-v1-0-0852530888e2@pks.im/).\n\n\n\n*Dieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.*\n\n\n\n## Verbesserte Leistung beim Generieren von Bundles\n\n\n\nGit bietet die Möglichkeit, über den Befehl\n\n\n[`git-bundle(1)` (in englischer Sprache verfügbar)](https://git-scm.com/docs/git-bundle) ein Archiv eines Repositories zu generieren, das einen\n\n\nbestimmten Satz von Referenzen und zugehörigen erreichbaren Objekten enthält. Dieser Vorgang\n\n\nwird von GitLab verwendet, um Repository-Backups zu erstellen, und ist auch ein Teil des\n\n\n[Bundle-URI (in englischer Sprache verfügbar)](https://git-scm.com/docs/bundle-uri)-Mechanismus.\n\n\n\nBei großen Repositories mit Millionen von Referenzen kann dieser Vorgang Stunden oder sogar Tage\n\n\ndauern. Zum Beispiel lagen die Backup-Zeiten für das Haupt-GitLab-Repository\n\n\n([gitlab-org/gitlab](https://gitlab.com/gitlab-org/gitlab)), bei\n\n\netwa 48 Stunden. Die Untersuchung zeigte einen Leistungsengpass, der\n\n\nauf die Art zurückzuführen war, wie Git eine Überprüfung durchführte, um zu vermeiden, dass doppelte Referenzen\n\n\nin das Bundle aufgenommen wurden. Die Implementierung verwendete eine verschachtelte `for`-Schleife, um alle aufgelisteten Referenzen zu durchlaufen und zu\n\n\nvergleichen, was zu einer Zeitkomplexität von O(N^2) führte. Die Skalierbarkeit\n\n\nist sehr schlecht, wenn die Anzahl der Referenzen in einem Repository zunimmt.\n\n\n\nIn dieser Version wurde dieses Problem behoben, indem die verschachtelten Schleifen durch eine \n\n\nDatenzuordnungsstruktur ersetzt wurden, was die Geschwindigkeit erheblich erhöht. Der folgende Benchmark zeigt\n\n\ndie Leistungssteigerung beim Erstellen eines Bundles mit einem Repository, das\n\n\n100 000 Referenzen enthält:\n\n\n\n```text\n\n\nBenchmark 1: bundle (refcount = 100000, revision = master) Time (mean ± σ):     14.653 s ±  0.203 s    [User: 13.940 s, System: 0.762 s] Range (min … max):   14.237 s … 14.920 s    10 runs\n\n\nBenchmark 2: bundle (refcount = 100000, revision = HEAD) Time (mean ± σ):      2.394 s ±  0.023 s    [User: 1.684 s, System: 0.798 s] Range (min … max):    2.364 s …  2.425 s    10 runs\n\n\nSummary bundle (refcount = 100000, revision = HEAD) ran 6.12 ± 0.10 times faster than bundle (refcount = 100000, revision = master)\n\n\n```\n\n\n\nWeitere Informationen findest du in unserem Blogbeitrag\n\n\n[Wie wir die Backup-Zeiten für GitLab-Repos von 48 Stunden auf 41 Minuten verringerten (in englischer Sprache verfügbar)](https://about.gitlab.com/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes/).\n\n\nDen ursprünglichen englischsprachigen Mailinglisten-Thread findest du\n\n\n[hier](https://lore.kernel.org/git/20250401-488-generating-bundles-with-many-references-has-non-linear-performance-v1-0-6d23b2d96557@gmail.com/).\n\n\n\n*Dieses Projekt wurde von [Karthik Nayak](https://gitlab.com/knayakgl) geleitet.*\n\n\n\n## Bessere Auflösung von URI-Bundles\n\n\n\nDurch den [Bundle-URI (in englischer Sprache verfügbar)](https://git-scm.com/docs/bundle-uri)-Mechanismus in Git können den Clients\n\n\nOrte zum Abrufen von Bundles zur Verfügung gestellt werden, um\n\n\nKlone und Abrufe zu beschleunigen. Wenn ein Client ein Bundle herunterlädt, werden Referenzen\n\n\nunter `refs/heads/*` zusammen mit\n\n\nden zugehörigen Objekten aus dem Bundle in das Repository kopiert. Ein Bundle kann zusätzliche Referenzen\n\n\naußerhalb von `refs/heads/*` enthalten, wie z. B. `refs/tags/*`, die einfach ignoriert werden, wenn\n\n\ndie Bundle-URI beim Klonen verwendet wird.\n\n\n\nIn Git 2.50 wird diese Einschränkung aufgehoben und alle Referenzen, die mit\n\n\n`refs/*` übereinstimmen und im heruntergeladenen Bundle enthalten sind, werden kopiert.\n\n\n[Scott Chacon](https://github.com/schacon), der diese Funktionalität beigesteuert hat,\n\n\ndemonstriert den Unterschied beim Klonen von\n\n\n[gitlab-org/gitlab-foss](https://gitlab.com/gitlab-org/gitlab-foss):\n\n\n\n```shell\n\n\n$ git-v2.49 clone --bundle-uri=gitlab-base.bundle https://gitlab.com/gitlab-org/gitlab-foss.git gl-2.49\n\n\nCloning into 'gl2.49'...\n\n\nremote: Enumerating objects: 1092703, done.\n\n\nremote: Counting objects: 100% (973405/973405), done.\n\n\nremote: Compressing objects: 100% (385827/385827), done.\n\n\nremote: Total 959773 (delta 710976), reused 766809 (delta 554276), pack-reused 0 (from 0)\n\n\nReceiving objects: 100% (959773/959773), 366.94 MiB | 20.87 MiB/s, done.\n\n\nResolving deltas: 100% (710976/710976), completed with 9081 local objects.\n\n\nChecking objects: 100% (4194304/4194304), done.\n\n\nChecking connectivity: 959668, done.\n\n\nUpdating files: 100% (59972/59972), done.\n\n\n\n$ git-v2.50 clone --bundle-uri=gitlab-base.bundle https://gitlab.com/gitlab-org/gitlab-foss.git gl-2.50\n\n\nCloning into 'gl-2.50'...\n\n\nremote: Enumerating objects: 65538, done.\n\n\nremote: Counting objects: 100% (56054/56054), done.\n\n\nremote: Compressing objects: 100% (28950/28950), done.\n\n\nremote: Total 43877 (delta 27401), reused 25170 (delta 13546), pack-reused 0 (from 0)\n\n\nReceiving objects: 100% (43877/43877), 40.42 MiB | 22.27 MiB/s, done.\n\n\nResolving deltas: 100% (27401/27401), completed with 8564 local objects.\n\n\nUpdating files: 100% (59972/59972), done.\n\n\n```\n\n\n\nWenn wir diese Ergebnisse vergleichen, sehen wir, dass Git 2.50 43 887 Objekte\n\n\n(40,42 MiB) abruft, nachdem das Bundle extrahiert wurde, während Git 2.49\n\n\ninsgesamt 959 773 Objekte (366,94 MiB) abruft. Git 2.50 ruft etwa 95 % weniger\n\n\nObjekte und 90 % weniger Daten ab, was vorteilhaft sowohl für den Client als auch für den Server ist. Der\n\n\nServer muss viel weniger Daten für den Client verarbeiten und der Client muss weniger Daten\n\n\nherunterladen und extrahieren. In dem von Scott angegebenen Beispiel führte dies zu einer\n\n\nBeschleunigung um 25 %.\n\n\n\nWeitere Informationen findest du im entsprechenden englischsprachigen\n\n\n[Mailinglisten-Thread](https://lore.kernel.org/git/pull.1897.git.git.1740489585344.gitgitgadget@gmail.com/).\n\n\n\n*Diese Patch-Serie wurde von [Scott Chacon](https://github.com/schacon) beigesteuert.*\n\n\n\n## Weiterlesen\n\n\n\nIn diesem Artikel werden nur einige der Beiträge von GitLab und\n\n\nder größeren Git-Community für diese neueste Veröffentlichung vorgestellt. Mehr darüber erfährst du in\n\n\nder [offiziellen Veröffentlichungsankündigung](https://lore.kernel.org/git/xmqq1prj1umb.fsf@gitster.g/) des Git-Projekts. Sieh dir auch\n\n\nunsere [letzten Blogbeiträge zu Git-Releases (in englischer Sprache verfügbar)](https://about.gitlab.com/blog/tags/git/)\n\n\nan, um weitere wichtige Beiträge von GitLab-Teammitgliedern zu entdecken.\n","2025-06-16",[9,681,269],{"featured":90,"template":685,"slug":880},"what-s-new-in-git-2-50-0","content:de-de:blog:what-s-new-in-git-2-50-0.yml","What S New In Git 2 50 0","de-de/blog/what-s-new-in-git-2-50-0.yml","de-de/blog/what-s-new-in-git-2-50-0",{"_path":886,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":887,"content":891,"config":897,"_id":899,"_type":13,"title":900,"_source":15,"_file":901,"_stem":902,"_extension":18},"/de-de/blog/what-s-new-in-git-2-51-0",{"config":888,"ogImage":875,"title":889,"description":890},{"noIndex":6},"Was ist neu in Git 2.51.0?","Erfahren Sie mehr über die neuesten Beiträge von GitLabs Git-Team und der Git-Community, einschließlich Performance-Optimierungen für git-push(1) und git-fetch(1), die besonders für deutsche Entwicklungsteams relevant sind.",{"title":889,"description":890,"authors":892,"heroImage":875,"date":894,"body":895,"category":679,"tags":896},[893],"Karthik Nayak","2025-08-18","Das Git-Projekt hat kürzlich [Git 2.51](https://lore.kernel.org/git/xmqqikikk1hr.fsf@gitster.g/T/#u) veröffentlicht. Aufgrund des Sommers auf der Nordhalbkugel und langsamerer Fortschritte war dieser Release-Zyklus mit 8 Wochen eher kurz (normalerweise dauert ein Release-Zyklus etwa 12 Wochen). \n\n**Die wichtigste Neuerung: Git-Operationen werden bis zu 22-mal schneller** - besonders bei großen Repositories mit vielen Branches profitieren Entwicklungsteams von erheblichen Performance-Verbesserungen.\n\nSchauen wir uns diese und andere bemerkenswerte Änderungen in diesem Release an, einschließlich Beiträgen vom Git-Team bei GitLab und der breiteren Git-Community.\n\n## Massive Performance-Verbesserungen: Von Sekunden zu Millisekunden\n\nGroße Repositories mit tausenden von Branches standen vor einem schmerzhaften Engpass. Git-Operationen, die Referenzen aktualisieren, konnten mehrere Sekunden dauern - ein echter Produktivitätskiller für Teams mit umfangreichen CI/CD-Pipelines oder Monorepo-Workflows.\n\n**Git 2.51.0 ändert alles. Eine 10.000-Referenzen-Fetch-Operation, die 3,4 Sekunden dauerte, wird jetzt in 154 Millisekunden abgeschlossen:**\n\n```\nVORHER: git-fetch mit 10.000 Referenzen\nTime: 3.403 s ± 0.775 s\n\nNACHHER: git-fetch mit 10.000 Referenzen  \nTime: 154.3 ms ± 17.6 ms\n\nERGEBNIS: 22× schneller\n```\n\n**Ähnlich dramatische Verbesserungen bei git-push:**\n\n```\nVORHER: git-push mit 10.000 Referenzen\nTime: 4.276 s ± 0.078 s\n\nNACHHER: git-push mit 10.000 Referenzen\nTime: 235.4 ms ± 6.9 ms\n\nERGEBNIS: 18× schneller\n```\n\n### Wie wurde das erreicht?\n\nDas Problem lag in der Art, wie Git Referenz-Transaktionen behandelte. Die Kommandos git-push(1) und git-fetch(1) erstellten eine separate Transaktion für jedes Referenz-Update, was enormen Overhead verursachte - jede Transaktion benötigte eine Initialisierungs- und Abbauphase und löste Auto-Komprimierungen aus.\n\nGit 2.51.0 verwendet nun **gebündelte Updates**: Mehrere Referenzen werden in einer einzigen Transaktion aktualisiert, während einzelne Updates weiterhin fehlschlagen dürfen. Dies eliminiert den Overhead und skaliert linear mit der Anzahl der Referenzen.\n\nDas Beste daran? Benutzer profitieren automatisch von diesen Verbesserungen, ohne Änderungen an ihrem Workflow vornehmen zu müssen.\n\nDieses [Projekt](https://lore.kernel.org/git/20250514-501-update-git-fetch-1-to-use-partial-transactions-v1-0-7c65f46493d4@gmail.com/) wurde von [Karthik Nayak](https://gitlab.com/knayakgl) geleitet.\n\n## Änderungen in Richtung Git 3.0\n\nVor 11 Jahren wurde Git 2.0 veröffentlicht, die letzte große Versionsfreigabe von Git. Obwohl wir keinen spezifischen Zeitplan für die nächste große Git-Veröffentlichung haben, enthält dieses Release Entscheidungen, die in Richtung Git 3.0 getroffen wurden.\n\nDie Git 3.0-Release-Planung ermöglicht es uns, Breaking Changes zu planen und zu implementieren und diese der erweiterten Git-Community zu kommunizieren. Neben der Dokumentation kann Git auch mit diesen Breaking Changes kompiliert werden für diejenigen, die mit diesen Änderungen experimentieren möchten. Weitere Informationen finden Sie im [BreakingChanges-Dokument](https://gitlab.com/gitlab-org/git/-/blob/master/Documentation/BreakingChanges.adoc).\n\nDas Git 2.51.0-Release bringt einige bedeutende Änderungen in Richtung Git 3.0.\n\n### \"reftable\" wird Standard in Git 3.0\n\nIm [Git 2.45.0](https://gitlab.com/gitlab-org/git/-/blob/master/Documentation/RelNotes/2.45.0.adoc?ref_type=heads)-Release wurde das \"reftable\"-Format als neues Backend zur Speicherung von Referenzen wie Branches oder Tags in Git eingeführt, das viele der Probleme des bestehenden \"files\"-Backends behebt. Lesen Sie unseren [Einsteiger-Leitfaden zur Funktionsweise von reftables](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/) für weitere Einblicke in das \"reftable\"-Backend.\n\nDas Git 2.51.0-Release markiert den Wechsel zur Verwendung des \"reftable\"-Formats als Standard in Git 3.0 für neu erstellte Repositories und verdrahtet die Änderung hinter einem Feature-Flag. Das \"reftable\"-Format bietet folgende Verbesserungen gegenüber dem traditionellen \"files\"-Backend:\n\n* Es ist unmöglich, zwei Referenzen zu speichern, die sich nur in der Groß-/Kleinschreibung unterscheiden, auf case-insensitiven Dateisystemen mit dem \"files\"-Format. Dieses Problem ist häufig auf Windows- und macOS-Plattformen. Da das \"reftable\"-Backend keine Dateisystem-Pfade zur Kodierung von Referenznamen verwendet, verschwindet dieses Problem.\n\n* Ebenso normalisiert macOS Pfadnamen, die Unicode-Zeichen enthalten, was zur Folge hat, dass Sie nicht zwei Namen mit Unicode-Zeichen speichern können, die unterschiedlich kodiert sind, mit dem \"files\"-Backend. Auch dies ist kein Problem mit dem \"reftable\"-Backend.\n\n* Das Löschen von Referenzen mit dem \"files\"-Backend erfordert, dass Git die komplette \"packed-refs\"-Datei neu schreibt. In großen Repositories mit vielen Referenzen kann diese Datei leicht dutzende Megabytes groß sein; in extremen Fällen kann sie Gigabytes umfassen. Das \"reftable\"-Backend verwendet Tombstone-Marker für gelöschte Referenzen und muss daher nicht alle seine Daten neu schreiben.\n\n* Repository-Hauskeeping mit dem \"files\"-Backend führt normalerweise All-into-One-Repacks von Referenzen durch. Dies kann sehr teuer sein, und folglich ist Housekeeping ein Kompromiss zwischen der Anzahl loser Referenzen, die sich ansammeln und Operationen verlangsamen, die Referenzen lesen, und der Komprimierung dieser losen Referenzen in die \"packed-refs\"-Datei. Das \"reftable\"-Backend verwendet geometrische Komprimierung nach jedem Schreibvorgang, was Kosten amortisiert und sicherstellt, dass das Backend immer in einem gut gewarteten Zustand ist.\n\n* Operationen, die mehrere Referenzen auf einmal schreiben, sind nicht atomisch mit dem \"files\"-Backend. Folglich kann Git Zwischenzustände sehen, wenn es Referenzen liest, während eine Referenz-Transaktion gerade auf die Festplatte committed wird.\n\n* Das Schreiben vieler Referenzen auf einmal ist langsam mit dem \"files\"-Backend, weil jede Referenz als separate Datei erstellt wird. Das \"reftable\"-Backend übertrifft das \"files\"-Backend um mehrere Größenordnungen.\n\n* Das \"reftable\"-Backend verwendet ein Binärformat mit Präfix-Komprimierung für Referenznamen. Als Resultat nutzt das Format weniger Platz im Vergleich zur \"packed-refs\"-Datei.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n### SHA-256 wird Standard in Git 3.0\n\nDas Git-Versionskontrollsystem speichert Objekte in einem inhaltsadressierbaren Dateisystem. Das bedeutet, es verwendet den Hash eines Objekts zur Adressierung von Inhalten wie Dateien, Verzeichnissen und Revisionen, anders als traditionelle Dateisysteme, die sequenzielle Nummern verwenden. Die Verwendung einer Hash-Funktion hat folgende Vorteile:\n\n* Einfache Integritätsprüfungen, da ein einzelner Bit-Flip die Hash-Ausgabe komplett verändern würde.\n* Schnelle Objektsuche, da Objekte nach ihrem Hash indexiert werden können.\n* Objektnamen können signiert werden und Drittparteien können dem Hash vertrauen, um das signierte Objekt und alle Objekte, auf die es verweist, zu adressieren.\n* Kommunikation über Git-Protokoll und Out-of-Band-Kommunikationsmethoden haben einen kurzen zuverlässigen String, der zur zuverlässigen Adressierung gespeicherter Inhalte verwendet werden kann.\n\nSeit seiner Entstehung hat Git den SHA-1-Hashing-Algorithmus verwendet. Sicherheitsforscher haben jedoch einige Schwachstellen in SHA-1 entdeckt, speziell den [SHAttered-Angriff](https://shattered.io), der eine praktische SHA-1-Hash-Kollision zeigt. Wir sind seit Git 2.13.0 standardmäßig zu einer gehärteten SHA-1-Implementierung übergegangen. SHA-1 ist jedoch immer noch ein schwacher Hashing-Algorithmus und es ist nur eine Frage der Zeit, bis zusätzliche Angriffe seine Sicherheit weiter reduzieren werden.\n\nSHA-256 wurde Ende 2018 als Nachfolger von SHA-1 identifiziert. Git 2.51.0 markiert es als Standard-Hash-Algorithmus für Git 3.0.\n\nDieses Projekt wurde von [brian m. carlson](https://github.com/bk2204) geleitet.\n\n### Entfernung von git-whatchanged(1)\n\nDer git-whatchanged(1)-Befehl zeigt Logs mit Unterschieden, die jeder Commit einführt. Obwohl dies nun von git log --raw abgelöst wurde, wurde der Befehl aus historischen Gründen beibehalten.\n\nGit 2.51.0 erfordert, dass Benutzer des Befehls explizit das --i-still-use-this-Flag verwenden, um alle Benutzer zu erfassen, die noch den veralteten Befehl verwenden, und markiert den Befehl auch für die Entfernung in Git 3.0.\n\nDieses Projekt wurde von [Junio C Hamano](https://simple.wikipedia.org/wiki/Junio_Hamano) geleitet.\n\n## git switch und git restore sind nicht mehr experimentell\n\nDer git-checkout(1)-Befehl kann für mehrere verschiedene Anwendungsfälle verwendet werden. Er kann zum Wechseln von Referenzen verwendet werden:\n\n```\n$ git status\nAuf Zweig master\nIhr Branch ist auf dem neuesten Stand mit 'origin/master'.\nNichts zu committen, Arbeitsverzeichnis unverändert\n\n$ git checkout next\nZu Branch 'next' gewechselt\nIhr Branch ist auf dem neuesten Stand mit 'origin/next'.\n```\n\nOder zur Wiederherstellung von Dateien:\n\n```\n$ echo \"additional line\" >> git.c\n\n$ git status\nAuf Zweig master\nIhr Branch ist auf dem neuesten Stand mit 'origin/master'.\n\nÄnderungen, die nicht zum Commit vorgemerkt sind:\n  (benutzen Sie \"git add \u003CDatei>...\", um die Änderungen zum Commit vorzumerken)\n  (benutzen Sie \"git restore \u003CDatei>...\", um die Änderungen im Arbeitsverzeichnis zu verwerfen)\n        geändert:       git.c\n\nkeine Änderungen zum Commit vorgemerkt (benutzen Sie \"git add\" und/oder \"git commit -a\")\n\n$ git checkout git.c\n1 Pfad von Index aktualisiert\n\n$ git status\nAuf Zweig master\nIhr Branch ist auf dem neuesten Stand mit 'origin/master'.\nNichts zu committen, Arbeitsverzeichnis unverändert\n```\n\nFür neue Git-Benutzer kann dies zu viel Verwirrung führen. In Git 2.33.0 wurden diese in zwei neue Befehle aufgeteilt: git-switch(1) und git-restore(1).\n\nDer git-switch(1)-Befehl ermöglicht es Benutzern, zu einem bestimmten Branch zu wechseln:\n\n```\n$ git status\nAuf Zweig master\nIhr Branch ist auf dem neuesten Stand mit 'origin/master'.\nNichts zu committen, Arbeitsverzeichnis unverändert\n\n$ git switch next\nZu Branch 'next' gewechselt\nIhr Branch ist auf dem neuesten Stand mit 'origin/next'.\n```\n\nUnd der git-restore(1)-Befehl ermöglicht es Benutzern, Working-Tree-Dateien wiederherzustellen:\n\n```\n$ echo \"additional line\" >> git.c\n\n$ git status\nAuf Zweig master\nIhr Branch ist auf dem neuesten Stand mit 'origin/master'.\n\nÄnderungen, die nicht zum Commit vorgemerkt sind:\n  (benutzen Sie \"git add \u003CDatei>...\", um die Änderungen zum Commit vorzumerken)\n  (benutzen Sie \"git restore \u003CDatei>...\", um die Änderungen im Arbeitsverzeichnis zu verwerfen)\n        geändert:       git.c\n\nkeine Änderungen zum Commit vorgemerkt (benutzen Sie \"git add\" und/oder \"git commit -a\")\n\n$ git restore git.c\n\n$ git status\nAuf Zweig master\nIhr Branch ist auf dem neuesten Stand mit 'origin/master'.\nNichts zu committen, Arbeitsverzeichnis unverändert\n```\n\nObwohl die beiden Befehle seit 2019 existieren, wurden sie als experimentell markiert. Der Effekt ist, dass das Git-Projekt keine Rückwärtskompatibilität für diese Befehle garantiert: das Verhalten kann sich jederzeit ändern. Obwohl die Absicht ursprünglich war, diese Befehle nach einigen Releases zu stabilisieren, ist das bis zu diesem Punkt nicht geschehen.\n\nDies hat zu mehreren Diskussionen auf der Git-Mailing-Liste geführt, wo Benutzer unsicher sind, ob sie diese neuen Befehle verwenden können oder ob sie eventuell wieder verschwinden. Da jedoch keine bedeutenden Änderungen vorgeschlagen wurden und einige Benutzer diese Befehle bereits verwenden, haben wir beschlossen, sie in Git 2.51 nicht mehr als experimentell zu deklarieren.\n\nDieses Projekt wurde von [Justin Tobler](https://gitlab.com/justintobler) geleitet.\n\n## git for-each-ref(1) erhält Paginierungs-Unterstützung\n\nDer git for-each-ref-Befehl wird verwendet, um alle im Repository vorhandenen Referenzen aufzulisten. Als Teil der Plumbing-Schicht von Git wird dieser Befehl häufig beispielsweise von Hosting-Forges verwendet, um Referenzen, die im Repository existieren, in ihrer UI aufzulisten. Aber während Repositories wachsen, wird es weniger realistisch, alle Referenzen auf einmal aufzulisten – schließlich können die größten Repositories Millionen davon enthalten! Stattdessen neigen Forges dazu, die Referenzen zu paginieren.\n\nDies zeigt eine wichtige Lücke auf: git-for-each-ref weiß nicht, Referenzen von vorherigen Seiten zu überspringen, die bereits gezeigt wurden. Folglich muss es möglicherweise eine große Anzahl uninteressanter Referenzen auflisten, bevor es endlich beginnt, die für die aktuelle Seite benötigten Referenzen zu liefern. Dies ist ineffizient und führt zu höherer als notwendiger Latenz oder sogar Timeouts.\n\nGit 2.51.0 unterstützt ein neues --start-after-Flag für git for-each-ref, das die Paginierung der Ausgabe ermöglicht. Dies kann auch mit dem --count-Flag kombiniert werden, um über einen Batch von Referenzen zu iterieren.\n\n```\n$ git for-each-ref --count=10\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-001\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-002\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-003\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-004\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-005\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-006\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-007\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-008\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-009\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-010\n\n$ git for-each-ref --count=10 --start-after=refs/heads/branch-010\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-011\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-012\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-013\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-014\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-015\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-016\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-017\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-018\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-019\n9751243fba48b34d29aabfc9784803617a806e81 commit    refs/heads/branch-020\n```\n\nDieses Projekt wurde von [Karthik Nayak](https://gitlab.com/knayakgl) geleitet.\n\n## Fazit\n\n**Diese Performance-Verbesserungen sind besonders relevant für deutsche Entwicklungsteams, die mit großen Repositories und intensiven CI/CD-Workflows arbeiten.** Die 22-fache Beschleunigung bei git-fetch kann erhebliche Zeitersparnisse in der täglichen Entwicklungsarbeit bedeuten.\n\nBereit, diese Verbeszerungen zu erleben? Aktualisieren Sie auf Git 2.51.0 und beginnen Sie, git switch und git restore in Ihrem täglichen Workflow zu verwenden.\n\nFür GitLab-Benutzer werden diese Performance-Verbesserungen automatisch Ihre Entwicklungserfahrung verbessern, sobald Ihre Git-Version aktualisiert wird.\n\nErfahren Sie mehr in den [offiziellen Git 2.51.0 Release Notes](https://lore.kernel.org/git/xmqqikikk1hr.fsf@gitster.g/T/#u) und erkunden Sie unser [komplettes Archiv der Git-Entwicklungsberichterstattung](https://about.gitlab.com/blog/tags/git/).\n\n---\n\n*Für vollständige technische Details, Benchmarks und Implementierungshinweise lesen Sie den [englischen Originalartikel](https://about.gitlab.com/blog/what-s-new-in-git-2-51-0/).*\n",[9,681,269,813],{"featured":6,"template":685,"slug":898},"what-s-new-in-git-2-51-0","content:de-de:blog:what-s-new-in-git-2-51-0.yml","What S New In Git 2 51 0","de-de/blog/what-s-new-in-git-2-51-0.yml","de-de/blog/what-s-new-in-git-2-51-0",{"_path":904,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":905,"content":911,"config":916,"_id":918,"_type":13,"title":919,"_source":15,"_file":920,"_stem":921,"_extension":18},"/de-de/blog/whats-new-in-git-2-45-0",{"ogTitle":906,"schema":907,"ogImage":908,"ogDescription":909,"ogSiteName":671,"noIndex":6,"ogType":672,"ogUrl":910,"title":906,"canonicalUrls":910,"description":909},"Was ist neu in Git 2.45.0?","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Was ist neu in Git 2.45.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2024-04-30\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659507/Blog/Hero%20Images/AdobeStock_623844718.jpg","Hier sind einige Highlights der Beiträge des Git-Teams von GitLab und der breiteren Git-Community zur neuesten Git-Version, darunter reftables und bessere Tools für Referenzen.","https://about.gitlab.com/blog/whats-new-in-git-2-45-0",{"title":906,"description":909,"authors":912,"heroImage":908,"date":913,"body":914,"category":679,"tags":915},[676],"2024-04-30","Das Git-Projekt hat kürzlich [Git-Version\n\n2.45.0](https://lore.kernel.org/git/xmqq8r0ww0sj.fsf@gitster.g/ \"Git Version\n\n2.45.0\") veröffentlicht. Werfen wir einen Blick auf die Highlights dieser\n\nVersion, die Beiträge des Git-Teams von GitLab und der gesamten\n\nGit-Community enthält.\n\n\n\n## Reftables: Ein neues Backend zum Speichern von Referenzen\n\n\n\nJedes Git-Repository muss zwei grundlegende Datenstrukturen erfassen:\n\n\n\n- Den Objektgraphen, der die Daten deiner Dateien, die Verzeichnisstruktur,\n\nCommit-Nachrichten und Tags speichert.\n\n\n- Referenzen, die auf diesen Objektgraphen verweisen, um bestimmte Objekte\n\nmit einem leichter verständlichen Namen zu verknüpfen. Ein Branch ist zum\n\nBeispiel eine Referenz, deren Name mit dem Präfix `refs/heads/` beginnt.\n\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n\nDas Format, in dem Referenzen in einem Repository auf der Festplatte\n\ngespeichert werden, ist seit der Einführung von Git weitgehend unverändert\n\ngeblieben und wird als „files“-Format bezeichnet. Jedes Mal, wenn du eine\n\nReferenz erstellst, legt Git eine sogenannte „lose Referenz“ an. Das ist\n\neine einfache Datei in deinem Git-Repository, deren Pfad mit dem Namen der\n\nReferenz übereinstimmt. Zum Beispiel:\n\n\n\n```shell\n\n\n$ git init .\n\n\nInitialized empty Git repository in /tmp/repo/.git/\n\n\n\n# Das Updaten einer Referenz veranlasst Git dazu, eine “lose Referenz”\n\n\n# zu erstellen. Diese lose Referenz ist eine einfache Datei, welche die\n\n\n# Objekt-ID des Commits enthält.\n\n\n$ git commit --allow-empty --message \"Initial commit\"\n\n\n[main (root-commit) c70f266] Initial commit\n\n\n$ cat .git/refs/heads/main\n\n\nc70f26689975782739ef9666af079535b12b5946\n\n\n\n# Wenn man eine zweite Referenz erstellt, wird diese als zweite lose\n\n\n# Referenz gespeichert.\n\n\n$ git branch feature\n\n\n$ cat .git/refs/heads/feature\n\n\nc70f26689975782739ef9666af079535b12b5946\n\n\n$ tree .git/refs\n\n\n.git/refs/\n\n\n├── heads\n\n\n│   ├── feature\n\n\n│   └── main\n\n\n└── tags\n\n\n\n3 directories, 2 files\n\n\n```\n\n\nVon Zeit zu Zeit packt Git diese Referenzen in ein „gepacktes“ Dateiformat,\n\ndamit es effizienter wird, Referenzen nachzuschlagen. Zum Beispiel:\n\n\n\n```shell\n\n\n# Wenn man Referenzen packt, erstellt Git eine “packed-refs” Datei.\n\n\n# Diese Datei enthält die sortierte Liste von vorher losen Referenzen.\n\n\n# Die losen Referenzen existieren nicht mehr.\n\n\n$ git pack-refs --all\n\n\n$ cat .git/refs/heads/main\n\n\ncat: .git/refs/heads/main: No such file or directory\n\n\n$ cat .git/packed-refs\n\n\n# pack-refs with: peeled fully-peeled sorted\n\n\nc70f26689975782739ef9666af079535b12b5946 refs/heads/feature\n\n\nc70f26689975782739ef9666af079535b12b5946 refs/heads/main\n\n\n```\n\n\nDieses Format ist zwar ziemlich simpel, hat aber Einschränkungen:\n\n\n\n- In großen Mono-Repos mit vielen Referenzen stießen wir auf Probleme mit\n\nder Skalierbarkeit. Das Löschen von Referenzen ist besonders ineffizient, da\n\ndie gesamte „packed-refs“-Datei neu geschrieben werden muss, um die\n\ngelöschte Referenz zu entfernen. In unseren größten Repositorys kann dies\n\ndazu führen, dass bei jedem Löschen einer Referenz mehrere Gigabyte an Daten\n\nneu geschrieben werden müssen.\n\n\n- Da mehrere Dateien gelesen werden müssen, um alle Referenzen des Repos zu\n\nermitteln, ist dies atomar nicht möglich. Sobald andere Prozesse existieren,\n\ndie in das Repo schreiben wollen, kann es dadurch zu Inkonsistenzen kommen.\n\n\n- Es ist unmöglich, atomar mehrere Referenzen gleichzeitig zu schreiben,\n\nweil dafür mehrere Dateien erstellt oder aktualisiert werden müssen.\n\n\n- Das Packen von Referenzen lässt sich nicht gut skalieren, weil die gesamte\n\n„packed-refs“-Datei neu geschrieben werden muss.\n\n\n- Da lose Referenzen den Dateisystempfad als Namen verwenden, unterliegen\n\nsie dem dateisystemspezifischen Verhalten. So können z. B. Dateisysteme, die\n\nGroß- und Kleinschreibung nicht unterscheiden, keine Referenzen speichern,\n\nbei denen nur die Groß- und Kleinschreibung unterschiedlich ist.\n\n\n\nUm diese Probleme zu lösen, wurde mit Git v2.45.0 ein neues\n\n„reftable“-Backend eingeführt, das ein neues Binärformat zum Speichern von\n\nReferenzen verwendet. Dieses neue Backend wird schon sehr lange entwickelt:\n\nes wurde ursprünglich von [Shawn\n\nPearce](https://sfconservancy.org/blog/2018/jan/30/shawn-pearce/ \"Shawn\n\nPearce\") im Juli 2017 vorgeschlagen und zunächst in\n\n[JGit](https://www.eclipse.org/jgit/ \"JGit\") implementiert. Das\n\n[Gerrit-Projekt](https://www.gerritcodereview.com/ \"Gerrit Projekt\") nutzt\n\nes bereits ausgiebig. Im Jahr 2021 hat [Han-Wen\n\nNienhuys](https://hanwen.home.xs4all.nl/ \"Han-Wen Nienhuys\") die Bibliothek\n\nin Git hochgeladen, die es ermöglicht, das reftable-Format zu lesen und zu\n\nschreiben.\n\n\n\nDas neue „reftable“-Backend, das wir in Git v2.45.0 hochgeladen haben,\n\nbringt nun endlich die reftable-Bibliothek und Git zusammen, so dass du das\n\nneue Format als Speicher-Backend in deinen Git-Repositorys verwenden kannst.\n\n\n\nWenn du mindestens Git v2.45.0 verwendest, kannst du neue Repositorys mit\n\ndem „reftable“-Format erstellen, indem du den Schalter\n\n`--ref-format=reftable` entweder an `git-init(1)` oder an `git-clone(1)`\n\nübergibst. Zum Beispiel:\n\n\n\n```shell\n\n\n$ git init --ref-format=reftable .\n\n\nInitialized empty Git repository in /tmp/repo/.git/\n\n\n$ git rev-parse --show-ref-format\n\n\nreftable\n\n\n$ find -type f .git/reftable/\n\n\n.git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n\n\n.git/reftable/tables.list\n\n\n\n$ git commit --allow-empty --message \"Initial commit\"\n\n\n$ find -type f .git/reftable/\n\n\n.git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n\n\n.git/reftable/0x000000000002-0x000000000002-87006b81.ref\n\n\n.git/reftable/tables.list\n\n\n```\n\n\nWie du siehst, werden die Referenzen jetzt im Verzeichnis `.git/reftable`\n\nstatt in `.git/refs` gespeichert. Die Referenzen und die Reflogs werden in\n\n„tables“ gespeichert. Das sind die Dateien, die auf `.ref` enden. Die Datei\n\n`tables.list` enthält die Liste aller derzeit aktiven Tabellen. Die\n\ntechnischen Details rund um die Funktionsweise werden wir in einem separaten\n\nBlogbeitrag erklären. Bleib dran!\n\n\n\nDas „reftable“-Backend ist als vollwertiger Ersatz für das „files“-Backend\n\ngedacht. Aus der Sicht der Benutzer(innen) sollte also alles gleich\n\nfunktionieren.\n\n\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab\n\n\"Patrick Steinhardt\") geleitet. Dank gebührt auch Shawn Pearce, dem Erfinder\n\ndes Formats, und Han-Wen Nienhuys, dem Autor der reftable-Bibliothek.\n\n\n\n## Bessere Tools für Referenzen \n\n\n\nDas Format „reftable“ löst zwar viele der Probleme, die wir haben, es bringt\n\nallerdings auch einige neue Probleme mit sich. Eines der wichtigsten\n\nProbleme ist die Zugänglichkeit der darin enthaltenen Daten.\n\n\n\nMit dem „files“-Backend kannst du im schlimmsten Fall deine normalen\n\nUnix-Tools verwenden, um den Zustand der Referenzen zu überprüfen. Sowohl\n\ndie „gepackten“ als auch die „losen“ Referenzen enthalten menschenlesbare\n\nDaten, die man leicht verstehen kann. Das ist beim „reftable“-Format anders,\n\nda es sich um ein Binärformat handelt. Daher muss Git alle notwendigen Tools\n\nbereitstellen, um Daten aus dem neuen „reftable“-Format zu extrahieren.\n\n\n\n### Auflisten aller Referenzen\n\n\n\nDas erste Problem bestand darin, dass es im Grunde unmöglich ist, alle\n\nReferenzen zu ermitteln, die ein Repository kennt. Das ist zunächst etwas\n\nrätselhaft: Du kannst über Git Referenzen erstellen und ändern, aber es kann\n\nnicht alle Referenzen auflisten, die es kennt?\n\n\n\nWährend es problemlos alle „normalen“ Referenzen auflisten kann, die mit dem\n\nPräfix `refs/` beginnen, verwendet Git auch sogenannte Pseudo-Referenzen.\n\nDiese Dateien befinden sich direkt im Stammverzeichnis des\n\nGit-Verzeichnisses und wären zum Beispiel Dateien wie `.git/MERGE_HEAD`. Das\n\nProblem dabei ist, dass diese Pseudo-Referenzen neben anderen Dateien\n\nliegen, die Git speichert, wie z. B. `.git/config`.\n\n\n\nWährend einige Pseudo-Referenzen bekannt und daher leicht zu identifizieren\n\nsind, gibt es theoretisch keine Grenzen dafür, welche Referenzen Git\n\nschreiben kann. Nichts hält dich davon ab, eine Referenz mit dem Namen\n\n„foobar“ zu erstellen.\n\n\n\nZum Beispiel:\n\n\n\n```shell\n\n\n$ git update-ref foobar HEAD\n\n\n$ cat .git/foobar\n\n\nf32633d4d7da32ccc3827e90ecdc10570927c77d\n\n\n```\n\n\nDas Problem des „files“-Backends ist, dass es Referenzen nur aufzählen kann,\n\nindem es Verzeichnisse durchsucht. Um herauszufinden, dass es sich bei\n\n`.git/foobar` tatsächlich um eine Referenz handelt, müsste Git die Datei\n\nöffnen und prüfen, ob sie wie eine Referenz formatiert ist oder nicht.\n\n\n\nDas „reftable“-Backend hingegen kennt sämtliche Referenzen, die es enthält:\n\nSie sind in seinen Datenstrukturen kodiert, so dass es lediglich diese\n\nReferenzen dekodieren und zurückgeben muss. Aufgrund der Einschränkungen des\n\n„files“-Backends gibt es jedoch kein Tool, mit dem du alle vorhandenen\n\nReferenzen ermitteln kannst.\n\n\n\nUm dieses Problem zu lösen, haben wir `git-for-each-ref(1)` mit dem neuen\n\nFlag `--include-root-refs` ausgestattet, das auch alle Referenzen auflistet,\n\ndie im Stammverzeichnis der Referenznamen-Hierarchie existieren. Zum\n\nBeispiel:\n\n\n\n```shell\n\n\n$ git for-each-ref --include-root-refs\n\n\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    HEAD\n\n\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    MERGE_HEAD\n\n\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    refs/heads/main\n\n\n```\n\n\nFür das „files“-Backend wird dieses neue Flag nach dem Best-Effort-Prinzip\n\nbehandelt, d.h. es werden alle Referenzen aufgenommen, die mit einem\n\nbekannten Pseudo-Referenznamen übereinstimmen. Für das „reftable“-Backend\n\nkönnen wir einfach alle bekannten Referenzen auflisten.\n\n\n\nDieses Projekt wurde von [Karthik Nayak](https://gitlab.com/knayakgl\n\n\"Karthik Nayak\") geleitet.\n\n\n\n### Auflisten aller reflogs\n\n\n\nJedes Mal, wenn du einen Branch aktualisierst, zeichnet Git diese\n\nBranch-Aktualisierung standardmäßig in einem sogenannten reflog auf. Dieses\n\nreflog ermöglicht es dir, Änderungen an diesem Branch rückgängig zu machen,\n\nfalls du eine unbeabsichtigte Änderung vorgenommen hast, und kann daher sehr\n\nhilfreich sein.\n\n\n\nMit dem „files“-Backend werden diese Protokolle in deinem\n\n`.git/logs`-Verzeichnis gespeichert:\n\n\n\n```shell\n\n\n$ find -type f .git/logs/\n\n\n.git/logs/HEAD\n\n\n.git/logs/refs/heads/main\n\n\n```\n\n\nTatsächlich ist die Auflistung der Dateien in diesem Verzeichnis die einzige\n\nMöglichkeit, um herauszufinden, welche Referenzen überhaupt ein reflog\n\nhaben. Dies ist ein Problem für das „reftable“-Backend, das diese Logs\n\nzusammen mit den Referenzen speichert. Folglich gibt es keine Möglichkeit\n\nmehr, herauszufinden, welche reflogs im Repository überhaupt existieren,\n\nwenn du das „reftable“ Format verwendest.\n\n\n\nDies ist jedoch nicht wirklich die Schuld des „reftable“-Formats, sondern\n\neine Lücke in den von Git bereitgestellten Tools. Um diese Lücke zu\n\nschließen, haben wir einen neuen Unterbefehl `list` für `git-reflog(1)`\n\neingeführt, mit dem du alle vorhandenen reflogs auflisten kannst:\n\n\n\n```shell\n\n\n$ git reflog list\n\n\nHEAD\n\n\nrefs/heads/main\n\n\n```\n\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab\n\n\"Patrick Steinhardt\") geleitet.\n\n\n\n### Effizienteres Packen von Referenzen\n\n\n\nUm effizient zu bleiben, müssen Git-Repositorys regelmäßig gewartet werden.\n\nNormalerweise wird diese Wartung durch verschiedene Git-Befehle ausgelöst,\n\ndie Daten in die Git-Repositorys schreiben, indem sie den Befehl `git\n\nmaintenance run --auto` ausführen. Dieser Befehl optimiert nur die\n\nDatenstrukturen, die tatsächlich optimiert werden müssen, damit Git keine\n\nComputeressourcen verschwendet.\n\n\n\nEine Datenstruktur, die von der Git-Wartung optimiert wird, ist die\n\nReferenzdatenbank, die mit dem Befehl `git pack-refs --all` optimiert wird.\n\nFür das „files“-Backend bedeutet dies, dass alle Referenzen in die\n\n„packed-refs“-Datei gepackt und die losen Referenzen gelöscht werden,\n\nwährend für das „reftable“-Backend alle Tabellen in einer einzigen Tabelle\n\nzusammengefasst werden.\n\n\n\nIm Hinblick auf das „files“-Backend können wir nicht viel besser vorgehen.\n\nDa die gesamte „packed-refs“-Datei ohnehin neu geschrieben werden muss, ist\n\nes sinnvoll, alle losen Referenzen zu packen.\n\n\n\nFür das „reftable“-Backend ist dies jedoch suboptimal, da sich das\n\n„reftable“-Backend selbst optimiert. Jedes Mal, wenn Git eine neue Tabelle\n\nan das „reftable“-Backend anhängt, führt es eine automatische Komprimierung\n\ndurch und führt die Tabellen nach Bedarf zusammen. Deshalb sollte sich die\n\nReferenzdatenbank immer in einem gut optimierten Zustand befinden, sodass\n\ndas Zusammenführen aller Tabellen vergebliche Mühe wäre.\n\n\n\nIn Git v2.45.0 haben wir daher einen neuen Modus `git pack-refs --auto`\n\neingeführt, der das Referenz-Backend auffordert, nach Bedarf zu optimieren.\n\nWährend das „files“-Backend auch bei gesetztem `--auto`-Flag weiterhin\n\ngleich funktioniert, verwendet das „reftable“-Backend die gleichen\n\nHeuristiken, die es bereits für seine automatische Komprimierung verwendet.\n\nIn der Praxis sollte dies in den meisten Fällen kein Problem darstellen.\n\n\n\nAußerdem wurde `git maintenance run --auto` so angepasst, dass das Flag\n\n`--auto` an `git-pack-refs(1)` übergeben wird, um diesen neuen Modus\n\nstandardmäßig zu verwenden.\n\n\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab\n\n\"Patrick Steinhardt\") geleitet. \n\n\n\n## Weiterlesen\n\n\n\nIn diesem Blogbeitrag ging es vor allem um das neue „reftable“-Backend, das\n\nes uns ermöglicht, in großen Repositorys mit vielen Referenzen besser zu\n\nskalieren, sowie um die zugehörigen Tools, die wir parallel dazu eingeführt\n\nhaben, damit es gut funktioniert. Natürlich hat die Git-Community mit dieser\n\nVersion auch verschiedene Leistungsverbesserungen, Fehlerbehebungen und\n\nkleinere Funktionen eingeführt. Diese kannst du in der [offiziellen\n\nVersionsankündigung](https://lore.kernel.org/git/xmqq8r0ww0sj.fsf@gitster.g/\n\n\"offiziellen Versionsankündigung\") des Git-Projekts nachlesen.\n",[9,269],{"slug":917,"featured":6,"template":685},"whats-new-in-git-2-45-0","content:de-de:blog:whats-new-in-git-2-45-0.yml","Whats New In Git 2 45 0","de-de/blog/whats-new-in-git-2-45-0.yml","de-de/blog/whats-new-in-git-2-45-0",{"_path":923,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":924,"content":929,"config":935,"_id":937,"_type":13,"title":938,"_source":15,"_file":939,"_stem":940,"_extension":18},"/de-de/blog/whats-new-in-git-2-46-0",{"title":925,"description":926,"ogTitle":925,"ogDescription":926,"noIndex":6,"ogImage":695,"ogUrl":927,"ogSiteName":671,"ogType":672,"canonicalUrls":927,"schema":928},"Was gibt es Neues in Git 2.46.0?","Hier findest du die Highlights, die das Git-Team von GitLab und die breitere Git-Community zum Release beigetragen haben. Freu dich unter anderem auf Migrationstools für das Referenz-Backend und Unterstützung für symbolische Referenzen in Transaktionen.","https://about.gitlab.com/blog/whats-new-in-git-2-46-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Was gibt es Neues in Git 2.46.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Justin Tobler\"}],\n        \"datePublished\": \"2024-07-29\",\n      }\n                  ",{"title":925,"description":926,"authors":930,"heroImage":695,"date":931,"body":932,"category":679,"tags":933,"updatedDate":934},[874],"2024-07-29","Das Git-Projekt hat kürzlich [Git v2.46.0](https://lore.kernel.org/git/xmqqzfq0i0qa.fsf@gitster.g/T/#u) veröffentlicht. Werfen wir einen Blick auf die wichtigsten Highlights dieser Version, die Beiträge des Git-Teams von GitLab und der gesamten Git-Community enthält.\n\n## Tools zur Migration von Referenz-Backends\n\nIn der vorherigen [Git 2.45.0](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.45.0.txt?ref_type=heads)-Release wurde das Format „reftables“ als neues Backend zum Speichern von Referenzen eingeführt. Dieses neue Referenzformat behebt einige Schwierigkeiten, die Repositories hatten, wenn die Anzahl der Referenzen stieg. Wenn du mit dem reftables-Backend noch nicht vertraut bist, lies dir unseren letzten [Blogbeitrag zur Git-Release](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/) durch, in dem das Feature vorgestellt wurde. Auch unsere Anfängerleitfaden ist toll, um [mehr darüber zu erfahren, wie reftables funktionieren](https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/).\n\nDas reftable-Backend hat ein anderes Festplattenformat als das vorhandene files-Backend. Daher ist bei der Verwendung von reftables in einem bestehenden Repository eine Konvertierung zwischen den verschiedenen Formaten erforderlich. Dazu wurden der neue Befehl git-refs(1) und der Unterbefehl `migrate` eingeführt, um Referenz-Backend-Migrationen auszuführen. Hier findest du ein Beispiel dafür, wie dieser Befehl verwendet werden kann.\n\n```shell\n# Initialisiere ein neues \"bare\" Repository, damit es keine Reflogs enthält.\n$ git init --bare .\n$ git commit --allow-empty -m \"init\"\n# Erstelle ein paar Referencen.\n$ git branch foo\n$ git branch bar\n$ tree .git/refs\n.git/refs\n├── heads\n│   ├── bar\n│   ├── foo\n│   ├── main\n└── tags\n# Migriere Referenzen zum reftable Format.\n$ git refs migrate --ref-format=reftable\n# Überprüfe, ob jetzt das reftable Backend benutzt wird.\n$ tree .git/reftable\n.git/reftable\n├── 0x000000000001-0x000000000001-a3451eed.ref\n└── tables.list\n# Überprüfe die Repository Konfiguration um das neue `refstorage` Format zu sehen.\n$ cat config\n[core]\n        repositoryformatversion = 1\n        filemode = true\n        bare = true\n        ignorecase = true\n        precomposeunicode = true\n[extensions]\n        refstorage = reftable\n```\n\nSobald ein Repository migriert wurde, wird das Festplattenformat geändert, sodass du dann das reftable-Backend nutzen kannst. Git-Abläufe im Repository funktionieren und interagieren wie gewohnt mit Remotes. Die Migration wirkt sich nur darauf aus, wie Referenzen intern für das Repository gespeichert werden. Wenn du zum file-Referenz-Backend zurückkehren möchtest, führe einfach den gleichen Befehl aus und spezifiziere dabei `--ref-format=files`.\n\nDas Migrationstool hat derzeit einige signifikante Einschränkungen. Die Reflogs in einem Repository werden auch über das Referenz-Backend gespeichert und würden ebenfalls eine Migration erfordern. Leider ist das Tool noch nicht in der Lage, Reflogs zwischen den files- und reftables-Backends zu konvertieren. Außerdem hat ein Repository mit Worktrees im Grunde mehrere Ref-Stores, und das Migrationstool kann dieses Szenario derzeit noch nicht bewältigen. Wenn ein Repository also Reflogs oder Worktrees enthält, ist die Migration derzeit nicht verfügbar. Diese Einschränkungen werden voraussichtlich in zukünftigen Versionen behoben.\n\nDa ein “bare” Git-Repository keine Reflogs hat, ist es einfacher zu migrieren. Um ein nicht-”bare” Repository zu migrieren, müssen die Reflogs zuerst gelöscht werden. Es kann also jedes Repository ohne Reflogs oder Worktrees migriert werden. Wenn du diese Einschränkungen im Hinterkopf behältst, kann dieses Tool ein guter Helfer sein, um die Vorteile des reftables-Backends in deinen bestehenden Repositories zu nutzen.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Transaktionale symref-Updates\n\nDer Befehl [git-update-ref(1)](https://git-scm.com/docs/git-update-ref)\nerlaubt es, Referenzen in einem Git-Repository zu schreiben. Es können auch mehrere Referenz-Updates atomar mit Transaktionen ausgeführt werden, indem der Befehl `git update-ref --stdin` verwendet wird und die Informationen zum Referenz-Update an stdin übergeben werden. Nachfolgend findest du ein Beispiel dafür, wie dies geschieht.\n\n```shell\n$ git init .\n$ git branch -m main\n$ git commit --allow-empty -m \"foo\" && git commit --allow-empty -m \"bar\"\n# Lese die Objekt ID für die zwei erstellten Commits.\n$ git rev-parse main~ main\n567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n# Starte eine Transaktion mit mehreren Updates und committe diese.\n$ git update-ref --stdin \u003C\u003CEOF\n> start\n> create refs/heads/new-ref 3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n> update refs/heads/main 567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n> commit\n> EOF\n$ git for-each-ref\n567aac2b3d1fbf0bd2433f669eb0b82a0348775e commit refs/heads/main\n3b13462a9a42e0a3130b9cbc472ab479d3ef0631 commit refs/heads/my-ref\n```\n\nIn diesem Beispiel wird nach dem Commit der Transaktion ein neuer Branch erstellt, der auf den Commit „bar“ zeigt, und der Haupt-Branch wird aktualisiert, um auf den vorherigen Commit „foo“ zu zeigen. Durch das Committen der Transaktion werden die angegebenen Referenz-Updates atomar durchgeführt. Wenn ein einzelnes Referenz-Update fehlschlägt, wird die Transaktion abgebrochen und es werden keine Referenz-Updates durchgeführt.\n\nHier ist bemerkenswert, dass es keine Anweisungen zur Unterstützung von symref-Updates bei diesen Transaktionen gibt. Wenn ein(e) Benutzer(in) ein symref zusammen mit anderen Referenzen atomar in derselben Transaktion aktualisieren möchte, gibt es dazu kein Tool. Die in dieser Release eingeführten Anweisungen `symref-create`, `symref-update`, `symref-delete` und `symref-verify` bieten diese Funktion.\n\n```shell\n# Erstelle eine symbolische Referenz, die wir updaten können.\n$ git symbolic-ref refs/heads/symref refs/heads/main\n# Der --no-deref Parameter wird benötigt, damit die symbolische Referenz selbst geupdated wird.\n$ git update-ref --stdin --no-deref \u003C\u003CEOF\n> start\n> symref-create refs/heads/new-symref refs/heads/main\n> symref-update refs/heads/symref refs/heads/new-ref\n> commit\n> EOF\n$ git symbolic-ref refs/heads/symref\nrefs/heads/new-ref\n$ git symbolic-ref refs/heads/new-symref\nrefs/heads/main\n```\n\nIm obigen Beispiel wird eine neue symbolische Referenz erstellt und eine weitere in einer Transaktion aktualisiert. Diese neuen symref-Anweisungen können in Kombination mit den bereits bestehenden Anweisungen verwendet werden, um alle Arten von Referenz-Updates jetzt in einer einzigen Transaktion durchführen zu können. Weitere Informationen zu jeder dieser neuen Anweisungen findest du in der [Dokumentation](https://git-scm.com/docs/git-update-ref).\n\nDieses Projekt wurde von [Karthik Nayak](https://gitlab.com/knayakgl) geleitet.\n\n## UX-Verbesserungen für git-config(1)\n\nMit dem Befehl git-config(1) können Repository-Optionen und globale Optionen angezeigt und konfiguriert werden. Die Modi, die für die Interaktion mit der Konfiguration verwendet werden, können explizit mit Hilfe von Flags ausgewählt oder implizit basierend auf der Anzahl der dem Befehl bereitgestellten Argumente bestimmt werden. Ein Beispiel:\n\n```shell\n$ git config --list\n# Lese den Nutzernamen im expliziten Modus.\n$ git config --get user.name\n# Lese den Nutzernamen im impliziten Modus.\n$ git config user.name\n# Schreibe den Nutzernamen im expliziten Modus.\n$ git config --set user.name \"Sidney Jones\"\n# Schreibe den Nutzernamen im impliziten Modus.\n$ git config user.name \"Sidney Jones\"\n# Man kann auch ein optionales drittes Argument übergeben. Was denkst du, was der Effekt ist?\n$ git config \u003Cname> [\u003Cvalue> [\u003Cvalue-pattern>]]\n```\n\nIm Allgemeinen entspricht die Benutzeroberfläche von [git-config(1)](https://git-scm.com/docs/git-config) nicht den anderen, moderneren Git-Befehlen, bei denen man normalerweise Unterbefehle verwendet. Ein Beispiel ist `git remote list`. In diesem Release werden `list`, `get`, `set`, `unset`, `rename-section`, `remove-section` und `edit` als Unterbefehle eingeführt, die mit dem config-Befehl verwendet werden können, während gleichzeitig die alte Syntax erhalten bleibt. Diese Änderung soll das Erlebnis der Benutzer(innen) verbessern, indem der config-Befehl den UI-Gewohnheiten entspricht und sich mehr an andere Befehle in Git angleicht. Zum Beispiel:\n\n```shell\n$ git config list\n$ git config get user.name\n$ git config set user.name \"Sidney Jones\"\n```\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Performance-Regression wurde behoben\n\nGit-Operationen, die Attribute nutzen, lesen die `.gitattributes` Dateien im Worktree des Repositorys. Dies ist für reine Git-Repositories problematisch, da diese per Definition keinen Worktree haben. Um dies zu umgehen, gibt es in Git die Konfiguration `attr.tree`, mit der ein Quellbaum definiert werden kann, von dem Attribute ausgelesen werden.\n\nIn der Git Release 2.43.0 hat Git begonnen, bei “bare” Repositories standardmäßig den Baum von `HEAD` als Quelle für Git-Attribute heranzuziehen. Leider führte diese zusätzliche Belastung durch die Suche nach Git-Attributdateien zu schweren Leistungseinbußen. Das liegt daran, dass bei jeder Attributsuche der komplette Quellbaum durchsucht wird, um nach einer zugeordneten `.gitattributes`-Datei zu suchen, wenn `attr.tree` festgelegt ist. Je größer und tiefer der Quellbaum des Repository ist, desto deutlicher wird die Performance-Regression. Benchmarks im linux.git-Repository zeigten beispielsweise, dass git-pack-objects(1) 1,68-mal länger braucht, um durchzulaufen. Dies kann zu Verzögerungen führen, wenn man beispielsweise git-clone(1) oder git-fetch(1) benutzt.\n\n```\n# attr.tree zeigt auf \"HEAD\", wie es in Git 2.43.0 Standard ist.\nBenchmark 1: git -c attr.tree=HEAD pack-objects --all --stdout \u003C/dev/null >/dev/null\n  Time (mean ± σ):     133.807 s ±  4.866 s    [User: 129.034 s, System: 6.671 s]\n  Range (min … max):   128.447 s … 137.945 s    3 runs\n\n# attr.tree zeigt auf einen leeren Baum, wie es in Versionen vor Git 2.43.0 Standard war.\nBenchmark 2: git -c attr.tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 pack-objects --all --stdout \u003C/dev/null >/dev/null\n  Time (mean ± σ):     79.442 s ±  0.822 s    [User: 77.500 s, System: 6.056 s]\n  Range (min … max):   78.583 s … 80.221 s    3 runs\n```\n\nEinige der wichtigsten Git-Befehle, die betroffen waren, sind `clone`, `pull`, `fetch` und `diff`, wenn diese wie erwähnt in Repositories mit großen oder tiefen Bäumen ausgeführt wurden. Um diese Performance-Regression zu beheben, wurde also die `attr.tree`-Konfiguration teilweise zurückgesetzt, sodass sie nicht mehr standardmäßig auf `HEAD` gesetzt ist. Weitere Informationen findest du in diesem [Thread](https://lore.kernel.org/git/CAKOHPAn1btewYTdLYWpW+fOaXMY+JQZsLCQxUSwoUqnnFN_ohA@mail.gmail.com/) in der Mailingliste.\n\n## Unit-Test-Migration\n\nIn der Vergangenheit wurde das Testen im Git-Projekt über End-to-End-Tests durchgeführt, die als Shell-Skripte implementiert waren. Vor relativ kurzer Zeit hat das Git-Projekt ein Unit-Test-Framework, das in C geschrieben ist, eingeführt. Dieses neue Test-Framework bietet die Möglichkeit für detailliertere Tests von Implementierungsdetails auf niedrigerer Ebene und stellt dadurch eine Ergänzung der bestehenden End-to-End Tests dar. Es gibt einige bestehende End-to-End-Tests, die besser als Unit-Tests und daher gut für die Portierung geeignet sind.\n\nIn diesem Jahr unterstützt GitLab erneut Mitwirkende des [Google Summer of Code (GSoC)](https://summerofcode.withgoogle.com/), die im Git-Projekt arbeiten. Dank dieser laufenden GSoC-Projekte und auch der großen Git-Community werden einige bestehende Tests überarbeitet und in das Unit-Test-Framework migriert. Während dieses letzten Release-Zyklus gab es mehrere Beiträge zur Verbesserung von Tests im Git-Projekt. Den Entwicklungsfortschritt dieser GSoC-Projekte kannst du auf den Blogs von [Chandra](https://chand-ra.github.io/) und [Ghanshyam](https://spectre10.github.io/posts/) verfolgen.\n\n## Bundle-URI-Fixes\n\nWenn ein Client etwas aus einem Remote-Repository abruft, werden normalerweise alle erforderlichen Objekte in einer vom Remote-Server zusammengestellten Packfile gesendet. Um einen Teil dieser Berechnungen einzusparen, können Server vorgefertigte „Bundles“ anbieten, die separat vom Remote-Server gespeichert werden und eine Reihe von Referenzen und Objekten enthalten, die der Client brauchen könnte. Der Client kann diese Pakete zuerst über einen Mechanismus namens [bundle-uri](https://git-scm.com/docs/bundle-uri) abrufen.\n\nDank [Xing Xin](https://lore.kernel.org/git/pull.1730.git.1715742069966.gitgitgadget@gmail.com/) wurde ein Problem identifiziert und behoben, bei dem Git trotz des Herunterladens einiger Bundles immer noch alles vom Remote-Server heruntergeladen hat, als gäbe es keine Bundles. Das Problem war, dass Git nicht alle heruntergeladenen Bundles korrekt erkannte, was dazu führte, dass die aufeinanderfolgenden Bundles vom Remote-Server abgerufen werden mussten. Dank diesem Fix können Remote-Server, die den Mechanismus bundle-uri verwenden, diese redundante Arbeit vermeiden und die Leistung verbessern.\n\n## Weiterlesen\n\nIn diesem Artikel wurden nur einige der Beiträge von GitLab und der breiteren Git-Community für dieses neueste Release vorgestellt. Mehr darüber erfährst du in der [offiziellen Release-Ankündigung](https://lore.kernel.org/git/xmqqzfq0i0qa.fsf@gitster.g/T/#u) des Git-Projekts. Sieh dir auch unsere [letzten Blogbeiträge zu Git-Releases](https://about.gitlab.com/blog/tags/git/) an, um weitere wichtige Beiträge von GitLab-Teammitgliedern zu entdecken.",[9,681,269],"2024-08-14",{"slug":936,"featured":90,"template":685},"whats-new-in-git-2-46-0","content:de-de:blog:whats-new-in-git-2-46-0.yml","Whats New In Git 2 46 0","de-de/blog/whats-new-in-git-2-46-0.yml","de-de/blog/whats-new-in-git-2-46-0",{"_path":942,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":943,"content":949,"config":955,"_id":957,"_type":13,"title":958,"_source":15,"_file":959,"_stem":960,"_extension":18},"/de-de/blog/whats-new-in-git-2-47-0",{"title":944,"description":945,"ogTitle":944,"ogDescription":945,"noIndex":6,"ogImage":946,"ogUrl":947,"ogSiteName":671,"ogType":672,"canonicalUrls":947,"schema":948},"Was gibt es Neues in Git 2.47.0?","Erfahre, was dich in der neuesten Version von Git erwartet, darunter neue globale Variablen zum Konfigurieren von Referenz- und Objekt-Hash-Formaten. Entdecke Beträge des Git-Teams von GitLab und der gesamten Git-Community.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663691/Blog/Hero%20Images/AdobeStock_752438815.jpg","https://about.gitlab.com/blog/whats-new-in-git-2-47-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Was gibt es Neues in Git 2.47.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Justin Tobler\"}],\n        \"datePublished\": \"2024-10-07\",\n      }\n                  ",{"title":944,"description":945,"authors":950,"heroImage":946,"date":951,"body":952,"category":679,"tags":953,"updatedDate":954},[874],"2024-10-07","Das Git-Projekt hat kürzlich [Git v2.47.0](https://lore.kernel.org/git/xmqqa5fg9bsz.fsf@gitster.g/) veröffentlicht.\nWerfen wir einen Blick auf die wichtigsten Highlights dieser Version, die Beiträge des Git-Teams von GitLab und der gesamten Git-Community enthält.\n\n## Neue globale Konfigurationsoptionen\n\nWenn du die letzten Git-Releases verfolgt hast, kennst du wahrscheinlich auch das Referenz-Backend „reftable“, das mit der [Git-Version 2.45](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-45-0/) eingeführt wurde. Weitere Informationen findest du in unserem [Anfängerleitfaden zum reftables-Format von Git](https://about.gitlab.com/de-de/blog/a-beginners-guide-to-the-git-reftable-format/). Um ein Repository im reftables-Format zu initialisieren, musste früher die Option `--ref-format` an git-init(1) übergeben werden:\n\n```sh\n$ git init --ref-format reftable\n```\n\nMit Release 2.47 gibt es in Git nun die Konfigurationsoption `init.defaultRefFormat`, die Git sagt, welches Referenz-Backend bei der Initialisierung eines Repositorys verwendet werden soll. Damit kann das Standard-Backend „Files“ überschrieben werden und du kannst beginnen, das reftables-Backend zu nutzen. Die Konfiguration funktioniert folgendermaßen:\n\n```sh\n$ git config set --global init.defaultRefFormat reftable\n```\n\nWie einige vielleicht wissen, ist auch das von Git-Repositories verwendete Objekt-Hash-Format konfigurierbar. Standardmäßig werden Repositories so initialisiert, dass sie das SHA-1-Objektformat verwenden. Eine Alternative ist das SHA-256-Format, das sicherer und zukunftssicherer ist. Weitere Informationen hierzu findest du in einem unserer [früheren Blogbeiträge zum SHA-256-Support in Gitaly](https://about.gitlab.com/blog/sha256-support-in-gitaly/#what-is-sha-256%3F). Ein SHA-256-Repository kann erstellt werden, indem die Option `--object-format' an git-init (1) übergeben wird:\n\n```sh\n$ git init --object-format sha256\n```\n\nIn dieser Git-Version wurde `init.defaultObjectFormat` als weitere Konfigurationsoption hinzugefügt. Diese Option sagt Git, welches Objektformat bei der Initialisierung eines Repositorys standardmäßig verwendet werden soll. Die Konfiguration funktioniert folgendermaßen:\n\n```sh\n$ git config set --global init.defaultObjectFormat sha256\n```\n\nBemerkenswert ist, dass SHA-256-Repositories nicht mit SHA-1 kompatibel sind und nicht alle Forges das Hosting von SHA-256-Repositories unterstützen. GitLab hat kürzlich [experimentelle Unterstützung für SHA-256-Repositories](https://about.gitlab.com/blog/gitlab-now-supports-sha256-repositories/) angekündigt, wenn du diese ausprobieren möchtest.\n\nDiese Optionen bieten eine gute Möglichkeit, diese Repository-Funktionen zu nutzen, ohne bei jeder Initialisierung eines neuen Repositorys bewusst daran denken zu müssen.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Neuer Unterbefehl für git-refs(1)\n\nIn der vorherigen Git-Version wurde der Befehl [git-refs (1)](https://git-scm.com/docs/git-refs) eingeführt, um einen Low-Level-Zugriff auf Referenzen in einem Repository zu ermöglichen und den Unterbefehl „migrate“ einzuführen, um zwischen den Referenz-Backends zu wechseln. In dieser Version wird der neue Unterbefehl „verify“ eingeführt, mit dem Benutzer(innen) die Referenzdatenbank auf Konsistenz überprüfen können. Um die Konsistenz eines Repositorys zu überprüfen, führen wir oft [git-fsck(1)](https://git-scm.com/docs/git-fsck) aus.\n\nDabei ist bemerkenswert, dass dieser Befehl die Referenzdatenbank des Repositorys jedoch nicht explizit verifiziert. Mit der Einführung des reftables-Referenzformats, das ein Binärformat ist und daher schwerer manuell zu überprüfen ist, ist es jetzt noch wichtiger, dass Werkzeuge zur Verfügung stehen, um diese Lücke zu schließen. Um das zu zeigen, wollen wir ein Repository mit einer ungültigen Referenz einrichten:\n\n```sh\n# Da das Backend \"files\" verwendet wird, können wir einfach eine ungültige Referenz erstellen.\n$ git init --ref-format files\n$ git commit --allow-empty -m \"init\"\n# Ein einzelnes '@' ist kein gültiger Referenzname.\n$ cp .git/refs/heads/main .git/refs/heads/@\n$ git refs verify\nerror: refs/heads/@: badRefName: invalid refname format\n```\n\nWir sehen hier, dass eine ungültige Referenz erkannt wurde und daher eine Fehlernachricht ausgegeben wird. Diese Werkzeuge werden zwar eher nicht von Endbenutzer(innen) ausgeführt, aber trotzdem sind sie insbesondere serverseitig praktisch, um sicherzustellen, dass Repositories konsistent bleiben. Das Ziel ist schlussendlich, diesen Befehl als Teil von git-fsck(1) zu integrieren und dadurch eine vereinheitlichte Möglichkeit zu schaffen, Konsistenzüberprüfungen von Repositories durchzuführen.\n\nDieses Projekt wurde von Jialuo She im Rahmen des Google Summer of Code geleitet. Weitere Informationen findest du im [GSoC-Bericht](https://luolibrary.com/2024/08/25/GSoC-Final-Report/) von Jialuo.\n\n## Laufende reftables-Arbeit\n\nDiese Version enthält auch Korrekturen für einige Fehler, die im reftables-Backend gefunden wurden. Einer dieser Fehler ist besonders interessant, denn er beeinflusst, wie die Tabellenkomprimierung durchgeführt wurde.\n\nDu erinnerst dich vielleicht daran, dass das reftables-Backend aus einer Reihe von Tabellen besteht, die den Status aller Referenzen im Repository enthalten. Jeder atomare Satz an Referenzenänderungen führt dazu, dass eine neue Tabelle geschrieben und in der Datei „tables.list“ erfasst wird. Um die Anzahl der vorhandenen Tabellen zu reduzieren, werden die Tabellen nach jeder Referenzaktualisierung komprimiert und geometrisch nach Dateigröße geordnet. Nachdem die Tabellen komprimiert wurden, wird die Datei „tables.list“ mit dem neuen Status der reftables auf dem Laufwerk aktualisiert.\n\nDas System ist so konzipiert, dass es gleichzeitig möglich ist, Tabellen zu schreiben und zu komprimieren. Die Synchronisation an bestimmten Punkten wird durch Lock-Dateien gesteuert. Wenn beispielsweise eine Komprimierung gestartet wird, wird die Datei „tables.list“ von vorneherein gesperrt, sodass die Datei konsistent gelesen werden kann und auch die Tabellen, die komprimiert werden müssen, gesperrt werden können. Da die eigentliche Tabellenkomprimierung etwas dauern kann, wird die Sperre aufgehoben, sodass gleichzeitige Schreibvorgänge fortgesetzt werden können. Das ist sicher, da gleichzeitige Schreiber(innen) wissen, dass sie die nun gesperrten Tabellen, die komprimiert werden sollen, nicht verändern dürfen. Wenn die neu komprimierten Tabellen fertig geschrieben wurden, wird die Datei „tables.list“ wieder gesperrt und wird dieses Mal aktualisiert, damit der neue Tabellenzustand angezeigt wird.\n\nEs gibt jedoch ein Problem: Was passiert, wenn bei einer gleichzeitigen Referenzaktualisierung eine neue Tabelle in die „tables.list“ geschrieben wird, während eine Tabellenkomprimierung läuft, nachdem die ursprüngliche Sperre aufgehoben wurde, aber bevor die neue Listendatei geschrieben wird? Wenn diese Situation eintreten würde, würde der Komprimierungsprozess nichts von der neuen Tabelle wissen und daher die Datei „tables.list“ ohne die neue Tabelle neu schreiben. Das verhindert in weiterer Folge die gleichzeitige Aktualisierung und könnte dazu führen, dass Referenzen nicht wie erwartet hinzugefügt, aktualisiert oder entfernt werden.\n\nGlücklicherweise ist die Lösung dieses Problems ziemlich einfach. Wenn der Komprimierungsvorgang die Sperre erhält, um in die „tables.list“ zu schreiben, muss er zuerst überprüfen, ob Aktualisierungen an der Datei vorgenommen wurden und dann die Datei neu laden. Auf diese Weise wird sichergestellt, dass alle gleichzeitigen Tabellenaktualisierungen auch entsprechend einbezogen werden. Weitere Informationen zu diesem Fix findest du im entsprechenden [Mailinglisten-Thread](https://lore.kernel.org/git/cover.1722435214.git.ps@pks.im/).\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Fixes für git-maintenance(1)\n\nWenn ein Repository wächst, ist es wichtig, dass es ordnungsgemäß gewartet wird. Standardmäßig führt Git [git-maintenance(1)](https://git-scm.com/docs/git-maintenance) nach bestimmten Operationen aus, damit der Zustand des Repositorys gesund bleibt. Um unnötige Wartung zu vermeiden, wird die Option `--auto` angegeben. Sie nutzt definierte Heuristiken, um zu bestimmen, ob Wartungsaufgaben ausgeführt werden sollen. Der Befehl kann so konfiguriert werden, dass er verschiedene Wartungsaufgaben durchführt. Standardmäßig führt er aber einfach [git-gc(1)](https://git-scm.com/docs/git-gc) im Hintergrund aus und ermöglicht es den Benutzer(innen), mit ihren Aufgaben fortzufahren.\n\nDies funktioniert wie erwartet, bis die Wartung für nicht standardmäßige Wartungsaufgaben konfiguriert ist. Wenn das passiert, werden die konfigurierten Wartungsaufgaben im Vordergrund ausgeführt und der ursprüngliche Wartungsprozess wird erst beendet, wenn alle Aufgaben abgeschlossen sind. Nur die Aufgabe „gc“ wird wie erwartet in den Hintergrund verschoben. Es hat sich gezeigt, dass sich git-gc(1), wenn es mit `--auto` ausgeführt wird, aus Versehen selbst verschob und andere Wartungsaufgaben keine Möglichkeit dazu hatten. Dies hatte das Potenzial, bestimmte Git-Befehle zu verlangsamen, da die automatische Wartung erst vollständig abgeschlossen werden musste, bevor sie beendet werden konnten.\n\nIn dieser Release wird das Problem behoben, indem git-maintenance(1) nun die Option `--detach` beigebracht wird, mit der der gesamte git-maintenance(1)-Prozess im Hintergrund läuft und nicht mehr nur einzelne Aufgaben. Die von Git durchgeführte automatische Wartung wurde ebenfalls aktualisiert, um diese neue Option zu verwenden. Weitere Informationen zu diesem Fix findest du im entsprechenden [Mailinglisten-Thread](https://lore.kernel.org/git/cover.1723533091.git.ps@pks.im/).\n\nWeiter oben wurde erwähnt, dass die automatische Wartung eine Reihe von Heuristiken verwendet, um festzustellen, ob bestimmte Wartungsvorgänge durchgeführt werden sollen oder nicht. Leider gibt es für das „files“-Referenz-Backend, wenn [git-pack-refs(1)](https://git-scm.com/docs/git-pack-refs) mit der Option `--auto` durchgeführt wird, keine solche Heuristik und lose Referenzen werden bedingungslos in eine „packed-refs“-Datei verpackt. Bei Repositories mit vielen Referenzen kann das erneute Schreiben der Datei „pack-refs“ ziemlich lange dauern.\n\nIn dieser Version wird daher eine Heuristik eingeführt, die entscheidet, ob lose Referenzen im „files“-Backend verpackt werden sollen. Diese Heuristik berücksichtigt die Größe der bestehenden „packed-refs“-Datei sowie die Anzahl der losen Referenzen im Repository. Je größer die „packed-refs“-Datei wird, umso höher wird die Schwelle für die Anzahl der losen Referenzen, bevor diese verpackt werden. Dadurch wird die Referenzverpackung im „files“-Backend weniger aggressiv und das Repository bleibt trotzdem gewartet. Sieh dir den entsprechenden [Mailinglisten-Thread](https://lore.kernel.org/git/cover.1725280479.git.ps@pks.im/) an, um mehr darüber zu erfahren.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Code-Refactoring und Verbesserungen der Wartbarkeit\n\nNeben funktionalen Änderungen wird auch an der Refaktorisierung gearbeitet und der Code wird bereinigt. Diese Verbesserungen sind wichtig, da sie dazu beitragen, dem Ziel des Projektes – die Libifizierung der internen Komponenten – näherzukommen. Hier findest du einen aktuellen [Update-Thread](https://lore.kernel.org/git/eoy2sjhnul57g6crprxi3etgeuacjmgxpl4yllstih7woyuebm@bd62ib3fi2ju/) zum Thema Libifizierung.\n\nEin Verbesserungsbereich war, Speicherlecks zu beheben. Das Git-Projekt weist einige Speicherlecks auf. In den meisten Fällen verursachen diese Lecks keine großen Probleme, da ein Git-Prozess normalerweise nur für eine kurze Zeit läuft und das System danach bereinigt wird, aber im Zusammenhang mit der Libifizierung sollte dies behoben werden. Tests im Projekt können mit einem Leck-Erkenner kombiniert werden, um Lecks zu erkennen. Aufgrund bestehender Lecks kann es jedoch schwierig zu validieren und durchzusetzen sein, dass neue Änderungen keine neuen Lecks einführen. Wir arbeiten kontinuierlich daran, alle Speicherlecks, die durch bestehende Tests im Projekt aufgedeckt werden, zu beheben. Leckfreie Tests werden anschließend mit `TEST_PASSES_SANITIZE_LEAK=true` gekennzeichnet, um anzuzeigen, dass sie in Zukunft voraussichtlich leckfrei sind. Vor dieser Release hatte das Projekt 223 Testdateien, die Speicherlecks enthielten. Mit dieser Version wurde die Zahl jetzt auf nur noch 60 gesenkt.\n\nAußerdem arbeiten wir weiterhin daran, die Verwendung globaler Variablen im gesamten Projekt zu reduzieren. Eine solche berüchtigte globale Variable ist `the_repository`, die den Status des Repositorys enthält, auf dem gearbeitet wird, und auf die im gesamten Projekt verwiesen wird. Diese Release enthält eine Reihe von Patches, mit denen `the_repository` entfernt und der Wert bei Bedarf direkt weitergegeben wird. Für Subsysteme im Git-Projekt, die immer noch von `the_repository` abhängig sind, ist `USE_THE_REPOSITORY_VARIABLE` definiert, sodass es global verwendet werden kann. Jetzt sind die Subsysteme refs, config und path nicht mehr auf deren Verwendung angewiesen.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) mit Unterstützung von [John Cai](https://gitlab.com/jcaigitlab) und [Jeff King](https://github.com/peff) geleitet.\n\n## Weiterlesen\n\nIn diesem Blogbeitrag werden nur einige der Beiträge von GitLab und der breiteren Git-Community für diese neueste Release vorgestellt. Mehr darüber erfährst du in der [offiziellen Release-Ankündigung](https://lore.kernel.org/git/xmqqa5fg9bsz.fsf@gitster.g/). Sieh dir auch unsere [letzten Blogbeiträge zu Git-Releases](https://about.gitlab.com/blog/tags/git/) an, um weitere wichtige Beiträge von GitLab-Teammitgliedern zu entdecken.\n\n- [Was gibt es Neues in Git 2.46.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-46-0/)\n- [Was gibt es Neues in Git 2.45.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-45-0/)\n- [Ein Anfängerleitfaden zum reftables-Format von Git](https://about.gitlab.com/de-de/blog/a-beginners-guide-to-the-git-reftable-format/)\n- [Git pull oder git fetch: Was ist der Unterschied?](https://about.gitlab.com/blog/git-pull-vs-git-fetch-whats-the-difference/)",[9,681,269],"2024-11-05",{"slug":956,"featured":90,"template":685},"whats-new-in-git-2-47-0","content:de-de:blog:whats-new-in-git-2-47-0.yml","Whats New In Git 2 47 0","de-de/blog/whats-new-in-git-2-47-0.yml","de-de/blog/whats-new-in-git-2-47-0",{"_path":962,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":963,"content":968,"config":975,"_id":977,"_type":13,"title":978,"_source":15,"_file":979,"_stem":980,"_extension":18},"/de-de/blog/whats-new-in-git-2-48-0",{"title":964,"description":965,"ogTitle":964,"ogDescription":965,"noIndex":6,"ogImage":946,"ogUrl":966,"ogSiteName":671,"ogType":672,"canonicalUrls":966,"schema":967},"Was gibt es Neues in Git 2.48.0?","Erfahre, was dich in der neuesten Version von Git erwartet, darunter ein neues Build-System und eine Optimierung im neuen reftables-Backend. Entdecke Beiträge des Git-Teams von GitLab und der Git-Community.","https://about.gitlab.com/blog/whats-new-in-git-2-48-0","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Was gibt es Neues in Git 2.48.0?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2025-01-10\",\n      }\n                  ",{"title":964,"description":965,"authors":969,"heroImage":946,"date":971,"body":972,"category":679,"tags":973,"updatedDate":974},[970],"Christian Couder","2025-01-10","Das Git-Projekt hat kürzlich [Git 2.48.0](https://lore.kernel.org/git/xmqqplku7cvm.fsf@gitster.g/). Werfen wir einen Blick auf die wichtigsten Highlights dieser Version, die Beiträge des Git-Teams von GitLab und der gesamten Git-Community enthält.\n\n## Meson-Build-System\n\nLange Zeit konnte Git entweder mit einem auf [Makefile](https://de.wikipedia.org/wiki/Make) oder auf [Autoconf](https://de.wikipedia.org/wiki/GNU_Build_System#GNU_Autoconf) basierenden Build-System erstellt werden. Git-Entwickler(innen) verwendeten bis jetzt hauptsächlich das auf Makefile basierende Build-System, weshalb [das auf Autoconf basierende Build-System hinsichtlich Funktionen und Wartung hinterherhinkte](https://lore.kernel.org/git/GV1PR02MB848925A79A9DD733848182D58D662@GV1PR02MB8489.eurprd02.prod.outlook.com/). Ein weiteres Problem war, dass viele Windows-Entwickler(innen) integrierte Entwicklungsumgebungen (IDEs) verwendeten, die auf Makefile und Autoconf basierende Build-Systeme nicht gut unterstützten.\n\nIm Jahr 2020 wurde die Unterstützung für die Entwicklung um Git und [CMake](https://cmake.org/) ergänzt. CMake bot eine bessere Windows-Unterstützung und IDE-Integration, insbesondere für Visual Studio. Einige moderne Build-Systemfunktionen wie Out-of-Source-Builds waren ebenfalls enthalten.\n\nVor kurzem schien es, dass der CMake-Support ebenfalls hinterherhinkte und dass es vielleicht keine gute Idee wäre, die beiden anderen Build-Systeme zu ersetzen. Also implementierte [Patrick Steinhardt](https://gitlab.com/pks-gitlab), GitLab Git Engineering Manager, Unterstützung für das [Meson-Build-System](https://mesonbuild.com/). Ziel dabei war, irgendwann die auf Autoconf, CMake und vielleicht sogar Makefile basierenden Build-Systeme zu ersetzen.\n\nDas neue, auf Meson basierende Build-System hat folgende Vorteile:\n* Benutzer(innen) können die verfügbaren Build-Optionen einfacher finden, was mit Makefiles und CMake schwierig ist.\n* Einfache Syntax im Vergleich zu Autoconf und CMake.\n* Viele verschiedene Betriebssysteme, Compiler und IDEs werden unterstützt.\n* Moderne Build-Systemfunktionen wie Out-of-Source-Builds werden unterstützt.\n\nHier ist ein Beispiel dafür, wie es tatsächlich zum Erstellen von Git verwendet werden kann:\n\n```shell\n$ cd git             \t# go into the root of Git's source code\n$ meson setup build/ \t# setup \"build\" as a build directory\n$ cd build           \t# go into the \"build\" directory\n$ meson compile      \t# actually build Git\n$ meson test         \t# test the new build\n$ meson install      \t# install the new build\n\n```\n\nMit `meson setup \u003Cbuild_dir>` können mehrere Build-Verzeichnisse eingerichtet werden, und die Konfiguration des Builds in einem Build-Verzeichnis kann durch Ausführen von `meson configure` im Build-Verzeichnis angezeigt oder geändert werden.\n\nWeitere Informationen zum Erstellen von Git mit Meson findest du oben in der [Datei `meson.build`](https://gitlab.com/gitlab-org/git/-/blob/master/meson.build) im Git-Code-Repository. Ein [Vergleich der verschiedenen Build-Systeme](https://gitlab.com/gitlab-org/git/-/blob/master/Documentation/technical/build-systems.txt) für Git ist als Teil der technischen Dokumentation von Git verfügbar.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Git ist hat jetzt keine Speicherlecks mehr (wie von der Testsuite ausgeführt)\n\nIn unserem Git-Release-Blogbeitrag zur vorherigen Release Git 2.47.0 sprachen wir über unsere [laufenden Bemühungen, alle Speicherlecks zu beheben](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-47-0/#code-refactoring-and-maintainability-improvements), die durch bestehende Tests im Projekt aufgedeckt wurden. Wir sagten, dass das Projekt vor der Git-Release 2.47.0 223 Testdateien hatte, die Speicherlecks enthielten, und dass dies nun auf 60 reduziert wurde.\n\nWir freuen uns, dass die Speicherlecks jetzt in allen 60 verbleibenden Testdateien behoben wurden. Dadurch hat Git, wie von der Testsuite gezeigt, nun keine Speicherlecks mehr. Dies ist ein wichtiger Schritt in Richtung des langjährigen Ziels, Git-interne Komponenten zu „libifizieren“ (also diese Komponenten in interne Bibliotheken zu konvertieren). Außerdem trägt es dazu bei, Git für die Speichernutzung zu optimieren.\n\nNun darf jeder neu hinzugefügte Test standardmäßig kein Leck enthalten. Es ist immer noch möglich, Tests mit Lecks zu haben, aber die Autor(inn)en müssen dafür eine Notlösung haben und gute Argumente liefern, warum der Test nicht ohne Lecks erstellt werden kann.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Verbesserte Bundle-URI-Checks\n\nIn unserem Git-Release-Blogbeitrag zur Release von Git 2.46.0 sprachen wir über einige [Bundle-URI-Fixes](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-46-0/#bundle-uri-fixes) von [Xing Xin](https://lore.kernel.org/git/pull.1730.git.1715742069966.gitgitgadget@gmail.com/).\nNach diesen Korrekturen arbeitete Xing Xin daran, dass [Abrufe mit Bundles](https://lore.kernel.org/git/pull.1730.v8.git.1718770053.gitgitgadget@gmail.com/) vollständig mit dem [fsck](https://git-scm.com/docs/git-fsck)-Mechanismus wie reguläre Abrufe überprüft werden konnten.\n\nBei der Validierung von regelmäßigen Abrufen ist es möglich, [verschiedene Schweregrade](https://git-scm.com/docs/git-fsck#Documentation/git-fsck.txt-fsckltmsg-idgt) für [verschiedene fsck-Probleme](https://git-scm.com/docs/git-fsck#_fsck_messages) festzulegen, um feiner steuern zu können, was in einem bestimmten Repository akzeptiert und was abgelehnt wird. Dies war zuvor für Abrufe mit Bundles nicht möglich.\n\nUm den Nutzen und die Sicherheit von [Bundle-URIs](https://git-scm.com/docs/bundle-uri) weiter zu erhöhen, haben wir [dieses Problem](https://lore.kernel.org/git/20241121204119.1440773-1-jltobler@gmail.com/) behoben, damit die verschiedenen Schweregrade, die für verschiedene fsck-Probleme festgelegt wurden, jetzt auch bei der Überprüfung von Abrufen mit Bundles verwendet werden können.\n\nDieses Projekt wurde von [Justin Tobler](https://gitlab.com/justintobler) geleitet.\n\n## Referenzkonsistenzprüfungen hinzufügen\n\nIn unserem Blogbeitrag zur Release von Git 2.47.0 erwähnten wir die Arbeit von Jialuo She an dem [neuen Unterbefehl „Verify“](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-47-0/#new-subcommand-for-git-refs(1) zu git-refs(1), der Teil des [Google Summer of Code 2024](https://summerofcode.withgoogle.com/archive/2024/projects/ukm4PTEF) (GSoC 2024) war.\n\nIn diesem Blogbeitrag erläuterten wir, dass das Ziel schlussendlich darin bestand, diesen neuen Unterbefehl als Teil von git-fsck(1) zu integrieren und dadurch eine vereinheitlichte Möglichkeit zu schaffen, Konsistenzüberprüfungen von Repositories durchzuführen. Jialuo She hat beschlossen, daran zu arbeiten, nachdem sein GSoC vorbei war.\n\nDas Ergebnis [dieser Arbeit](https://lore.kernel.org/git/ZrtrT1CPI4YUf5db@ArchLinux/) ist, dass git-fsck(1) jetzt eine Reihe von referenzbezogenen Problemen erkennen und beheben kann, z. B. wenn der Inhalt einer Referenz schlecht ist, wenn ein symbolischer Link als symbolische Referenz verwendet wird oder wenn das Ziel einer symbolischen Referenz nicht auf eine gültige Referenz verweist. Wir müssen weiterhin `git refs verify` als Teil von git-fsck(1) aufrufen und erstere alle nicht backendspezifischen Überprüfungen durchführen lassen, die letztere derzeit durchführt, aber wir sind unserem Ziel einer vereinheitlichten Möglichkeit, alle Konsistenzüberprüfungen von Refs durchzuführen, ein Stückchen näher gekommen.\n\nDieses Projekt wurde von Jialuo She geleitet.\n\n## Iterator-Wiederverwendung in reftables\n\nIn der Version [Git 2.45.0](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.45.0.txt) wurde das reftables-Format als neues Backend zum Speichern von Referenzen (meist Branches und Tags) eingeführt. Wenn du mit dem reftables-Backend noch nicht vertraut bist, lies dir unseren letzten [Blogbeitrag zur Git-Release](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-45-0/) durch, in dem das Feature vorgestellt wurde. Auch unsere Anfängerleitfaden ist toll, um [mehr darüber zu erfahren, wie reftables funktionieren](https://about.gitlab.com/de-de/blog/a-beginners-guide-to-the-git-reftable-format/).\n\nSeit dieser Release haben wir dieses Backend weiter verbessert und uns in letzter Zeit darauf konzentriert, seine Leistung zu verbessern, indem wir beim Lesen zufälliger Referenzen [einige interne Iteratoren wiederverwenden](https://lore.kernel.org/git/cover.1730732881.git.ps@pks.im/). Vor diesen Änderungen musste beim Lesen einer einzelnen Referenz ein ganz neuer Iterator erstellt, an der richtigen Stelle in den jeweiligen Tabellen gesucht und dann der nächste Wert daraus gelesen werden, was beim Lesen vieler Referenzen in schneller Folge ziemlich ineffizient sein kann. Nach der Änderung erstellen wir jetzt nur noch einen einzigen Iterator und verwenden ihn wieder, um mehrere Referenzen zu lesen, wodurch wir etwas Overhead sparen.\n\nDadurch verbessert sich die Leistung in einer Reihe von reftables-bezogenen Anwendungsfällen, so etwa ist das Erstellen vieler Referenzen in einer Transaktion, die viele zufällige Lesevorgänge durchführt, um 7 % schneller. Darüber hinaus schafft dies die Möglichkeit für weitere Optimierungen, da wir weiterhin mehr Zustände in den Iteratoren wiederverwenden können.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Unterstützung für reflogs in `git-refs migrate`\n\nNachdem das reftables-Backend in Git 2.45.0 eingeführt wurde (siehe obigen Abschnitt), haben wir in Git 2.46.0 an Tools zur Migration von Referenz-Backends gearbeitet. Ziel war, einen neuen Unterbefehl `migrate` zu git-refs(1) hinzuzufügen.\n\nIm Artikel über Git 2.46.0 [ging es um diese Arbeit](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-46-0/#tooling-to-migrate-reference-backends) und einige der Einschränkungen, die noch existierten. In dem Artikel heißt es insbesondere:\n\n„Die reflogs in einem Repository werden auch über das Referenz-Backend gespeichert und würden ebenfalls eine Formatmigration erfordern. Leider ist das Tool noch nicht in der Lage, reflogs zwischen den files- und reftables-Backends zu konvertieren.“\n\nWir freuen uns, dass wir [diese Einschränkung in Git 2.48.0 behoben haben](https://lore.kernel.org/git/20241216-320-git-refs-migrate-reflogs-v4-0-d7cd3f197453@gmail.com/).\nReflogs können jetzt auch mit `git refs migrate` migriert werden. Das Migrationstool ist noch nicht in der Lage, ein Repository mit mehreren Arbeitsbäumen zu verwalten, aber dies ist die einzige verbleibende Einschränkung. Wenn du keine Arbeitsbäume verwendest, kannst du das reftables-Backend bereits in deinen vorhandenen Repositories nutzen.\n\nDieses Projekt wurde von [Karthik Nayak](https://gitlab.com/knayakgl) geleitet.\n\n## Optimierung von „ref-filter“\n\nDas Subsystem „ref-filter“ ist ein Formatierungscode, der von Befehlen wie `git for-each-ref`, `git branch` und `git tag` verwendet wird, um Informationen zu Git-Referenzen zu sortieren, zu filtern, zu formatieren und anzuzeigen.\n\nWenn Repositories wachsen, können sie eine große Anzahl von Referenzen enthalten. Aus diesem Grund arbeiten wir nicht nur daran, Backends zu verbessern, die Referenzen speichern, wie das reftables-Backend (siehe oben), sondern auch den Formatierungscode zu optimieren, wie zum Beispiel das Subsystem „ref-filter“.\n\nWir haben kürzlich [einen Weg gefunden](https://lore.kernel.org/git/d23c3e3ee7fdb49fcd05b4f2e52dd2a1cfdc10f2.1729510342.git.ps@pks.im/), wie wir vermeiden können, dass Referenzen vorübergehend gepuffert und im ref-Filtercode mehrmals wiederholt werden, wenn sie in der gleichen Sortierreihenfolge verarbeitet werden sollen, wie sie von den Backends bereitgestellt wird. Dies führt zu Speichereinsparungen und macht bestimmte Befehle in einigen Fällen bis zu 770-mal schneller.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## Weiterlesen\n\nIn diesem Blogbeitrag werden nur einige der Beiträge von GitLab und der ganzen Git-Community für diese neueste Release vorgestellt. Diese kannst du in der offiziellen Versionsankündigung des Git-Projekts nachlesen. Sieh dir auch unsere [letzten Blogbeiträge zu Git-Releases](https://about.gitlab.com/blog/tags/git/) an, um weitere wichtige Beiträge von GitLab-Teammitgliedern zu entdecken.\n\n- [Was gibt es Neues in Git 2.47.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-47-0/)\n- [Was gibt es Neues in Git 2.46.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-46-0/)\n- [Was gibt es Neues in Git 2.45.0](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-45-0/)\n- [Der Anfängerleitfaden zum „reftables“-Format von Git](https://about.gitlab.com/de-de/blog/a-beginners-guide-to-the-git-reftable-format/)\n",[9,681,269],"2025-01-20",{"slug":976,"featured":90,"template":685},"whats-new-in-git-2-48-0","content:de-de:blog:whats-new-in-git-2-48-0.yml","Whats New In Git 2 48 0","de-de/blog/whats-new-in-git-2-48-0.yml","de-de/blog/whats-new-in-git-2-48-0",{"_path":982,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":983,"content":988,"config":996,"_id":998,"_type":13,"title":999,"_source":15,"_file":1000,"_stem":1001,"_extension":18},"/de-de/blog/whats-new-in-git-2-49-0",{"ogTitle":984,"schema":985,"ogImage":875,"ogDescription":986,"ogSiteName":671,"noIndex":6,"ogType":672,"ogUrl":987,"title":984,"canonicalUrls":987,"description":986},"Was gibt es Neues in Git 2.49.0?","{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Article\",\n  \"@headline\": \"Was gibt es Neues in Git 2.49.0?\",\n  \"author\": [{\"@type\":\"Person\",\"name\":\"Toon Claes\"}],\n  \"datePublished\": \"2025-03-14\"\n}\n","Erfahre mehr über die neueste Version von Git, einschließlich verbesserter Leistung dank zlib-ng, einem neuen Algorithmus zum Hashing von Namen und git-backfill(1).","https://about.gitlab.com/blog/whats-new-in-git-2-49-0",{"heroImage":875,"body":989,"authors":990,"updatedDate":992,"date":993,"title":994,"tags":995,"description":986,"category":679},"Das Git-Projekt hat kürzlich\n[Git 2.49.0](https://lore.kernel.org/git/xmqqfrjfilc8.fsf@gitster.g/)\nveröffentlicht. Werfen wir einen Blick auf die Highlights dieser Version,\ndie Beiträge des Git-Teams von GitLab und der gesamten Git-Community\nenthält.\n\n\nDas erwartet dich:\n\n- [git-backfill(1) und die neue Pfad-API](#git-backfill(1)-and-the-new-path-walk-api)\n\n- [Einführung von zlib-ng](#introduction-of-zlib-ng)\n\n- [Weitere Iteration auf Meson](#continued-iteration-on-meson)\n\n- [Einstellung von .git/branches/ und .git/remotes/](#deprecation-of-.gitbranches%2F-and-.git%2Fremotes%2F)\n\n- [Rust-Datenbindungen für libgit](#rust-bindings-for-libgit)\n\n- [Neuer Namenshashing-Algorithmus](#new-name-hashing-algorithm)\n\n- [Promisor-Remote-Fähigkeit](#promisor-remote-capability)\n\n- [Flacher Klon mit `--revision`](#thin-clone-using---revision)\n\n\n## git-backfill(1) und die neue Pfad-API\n\n\nWenn du ein Git-Repository [mit `git-clone(1)` klonst](https://git-scm.com/docs/git-clone/de), kannst du die Option [`--filter`](https://git-scm.com/docs/git-clone/de#git-clone---filterltFilter-Spezifikationgt) übergeben. Mit dieser Option kannst du einen _partiellen Klon_ erstellen. In einem partiellen Klon sendet der Server nur eine Teilmenge der erreichbaren Objekte gemäß dem angegebenen Objektfilter. Wenn du beispielsweise einen Klon mit `--filter=blob:none` erstellst, werden keine Blobs (Dateiinhalte) vom Server abgerufen und es wird ein _blobless Klon_ erstellt.\n\n\nBlobless-Klone haben alle erreichbaren Commits und Verzeichnisse, aber keine Blobs. Wenn du einen Vorgang wie [`git-checkout(1)`](https://git-scm.com/docs/git-checkout) durchführst, lädt Git die fehlenden Blobs herunter, um den Vorgang abzuschließen. Bei einigen Operationen wie [`git-blame(1)`](https://git-scm.com/docs/git-blame) kann dies dazu führen, dass Objekte einzeln heruntergeladen werden, wodurch der Befehl deutlich langsamer wird.\n\nDiese Leistungseinbuße der Performance tritt auf, weil `git-blame(1)` den Commit-Verlauf durchsuchen muss, um herauszufinden, welche spezifischen Blobs benötigt werden. Dann muss es jeden fehlenden Blob einzeln beim Server anfragen.\n\n\nIn Git 2.49 wird der neue Unterbefehl `git-backfill(1)` eingeführt, der verwendet werden kann, um fehlende Blobs in einem partiellen Blobless-Klon herunterzuladen.\n\n\nIm Hintergrund nutzt der Befehl `git-backfill(1)` die neue Pfad-API, die sich davon unterscheidet, wie Git normalerweise über Commits iteriert. Anstatt die Commits einzeln durchzugehen und die mit jedem Commit verbundenen Strukturen und Blobs rekursiv zu besuchen, durchläuft die Path-walk API die Daten nach Pfaden. Für jeden Pfad fügt sie eine Liste der assoziierten Strukturobjekte zu einem Verarbeitungsstapel hinzu. Dieser Verarbeitungsstapel wird dann in der Reihenfolge „Depth-First“ verarbeitet. Anstatt also jedes Objekt im Commit `1` zu verarbeiten, bevor sie zu Commit `2` weitergeht, verarbeitet die API alle Versionen von Datei `A` in allen Commits, bevor sie zu Datei `B` weitergeht. Dieser Ansatz verbessert die Leistung in Szenarien, in denen die Gruppierung nach Pfad unerlässlich ist, erheblich.\n\n\nIch verdeutliche dies in diesem Beispiel, indem ich einen Blobless-Klon von [`gitlab-org/git`](https://gitlab.com/gitlab-org/git) erstelle:\n\n\n\n```shell\n\n$ git clone --filter=blob:none --bare --no-tags git@gitlab.com:gitlab-org/git.git\n\nCloning into bare repository 'git.git'...\n\nremote: Enumerating objects: 245904, done.\n\nremote: Counting objects: 100% (1736/1736), done.\n\nremote: Compressing objects: 100% (276/276), done.\n\nremote: Total 245904 (delta 1591), reused 1547 (delta 1459), pack-reused 244168 (from 1)\n\nReceiving objects: 100% (245904/245904), 59.35 MiB | 15.96 MiB/s, done.Resolving deltas: 100% (161482/161482), done.\n\n```\n\n\nOben verwenden wir `--bare`, um sicherzustellen, dass Git keine Blobs herunterladen muss, um den initialen Branch zu überprüfen. Wir können verifizieren, dass dieser Klon keine Blobs enthält:\n\n\n```sh\n\n$ git cat-file --batch-all-objects --batch-check='%(objecttype)' | sort | uniq -c\n  83977 commit\n 161927 tree\n```\n\n\nWenn du die Inhalte einer Datei im Repository anzeigen möchtest, muss Git sie herunterladen:\n\n\n```sh\n\n$ git cat-file -p HEAD:README.md\n\nremote: Enumerating objects: 1, done.\n\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 1 (from 1)\n\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\n\n\n[![Build status](https://github.com/git/git/workflows/CI/badge.svg)](https://github.com/git/git/actions?query=branch%3Amaster+event%3Apush)\n\n\nGit - fast, scalable, distributed revision control system\n\n=========================================================\n\n\nGit is a fast, scalable, distributed revision control system with an\n\nunusually rich command set that provides both high-level operations\n\nand full access to internals.\n\n\n[snip]\n\n```\n\n\nWie du oben sehen kannst, kommuniziert Git zuerst mit dem Remote-Repository, um den Blob herunterzuladen, bevor er angezeigt werden kann.\n\n\nWenn du `git-blame(1)` für die Datei ausführen möchtest, muss es viel mehr herunterladen:\n\n\n```sh\n\n$ git blame HEAD README.md\n\nremote: Enumerating objects: 1, done.\n\nremote: Counting objects: 100% (1/1), done.\n\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\n\nremote: Enumerating objects: 1, done.\n\nremote: Counting objects: 100% (1/1), done.\n\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\n\nremote: Enumerating objects: 1, done.\n\nremote: Counting objects: 100% (1/1), done.\n\nremote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)\n\nReceiving objects: 100% (1/1), 1.64 KiB | 1.64 MiB/s, done.\n\nremote: Enumerating objects: 1, done.\n\n\n[snip]\n\n\ndf7375d772 README.md (Ævar Arnfjörð Bjarmason 2021-11-23 17:29:09 +0100  1) [![Build status](https://github.com/git/git/workflows/CI/badge.svg)](https://github.com/git/git/actions?query=branch%3Amaster+event%3Apush)\n\n5f7864663b README.md (Johannes Schindelin \t2019-01-29 06:19:32 -0800  2)\n\n28513c4f56 README.md (Matthieu Moy        \t2016-02-25 09:37:29 +0100  3) Git - fast, scalable, distributed revision control system\n\n28513c4f56 README.md (Matthieu Moy        \t2016-02-25 09:37:29 +0100  4) =========================================================\n\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  5)\n\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  6) Git is a fast, scalable, distributed revision control system with an\n\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  7) unusually rich command set that provides both high-level operations\n\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  8) and full access to internals.\n\n556b6600b2 README\t(Nicolas Pitre       \t2007-01-17 13:04:39 -0500  9)\n\n\n[snip]\n\n```\n\n\nWir haben die Ausgabe abgeschnitten, aber du siehst, dass Git für jede Revision dieser Datei separat auf den Server zugreift. Das ist wirklich ineffizient. Mit `git-backfill(1)` können wir Git anweisen, alle Blobs herunterzuladen:\n\n\n```shell\n\n$ git backfill\n\nremote: Enumerating objects: 50711, done.\n\nremote: Counting objects: 100% (15438/15438), done.\n\nremote: Compressing objects: 100% (708/708), done.\n\nremote: Total 50711 (delta 15154), reused 14730 (delta 14730), pack-reused 35273 (from 1)\n\nReceiving objects: 100% (50711/50711), 11.62 MiB | 12.28 MiB/s, done.\n\nResolving deltas: 100% (49154/49154), done.\n\nremote: Enumerating objects: 50017, done.\n\nremote: Counting objects: 100% (10826/10826), done.\n\nremote: Compressing objects: 100% (634/634), done.\n\nremote: Total 50017 (delta 10580), reused 10192 (delta 10192), pack-reused 39191 (from 1)\n\nReceiving objects: 100% (50017/50017), 12.17 MiB | 12.33 MiB/s, done.\n\nResolving deltas: 100% (48301/48301), done.\n\nremote: Enumerating objects: 47303, done.\n\nremote: Counting objects: 100% (7311/7311), done.\n\nremote: Compressing objects: 100% (618/618), done.\n\nremote: Total 47303 (delta 7021), reused 6693 (delta 6693), pack-reused 39992 (from 1)\n\nReceiving objects: 100% (47303/47303), 40.84 MiB | 15.26 MiB/s, done.\n\nResolving deltas: 100% (43788/43788), done.\n\n```\n\n\nDadurch werden alle Blobs wieder aufgefüllt und der Blobless-Klon wird zu einem vollständigen Klon:\n\n\n```shell\n\n$ git cat-file --batch-all-objects --batch-check='%(objecttype)' | sort | uniq -c\n 148031 blob\n  83977 commit\n 161927 tree\n```\n\n\nDieses [Projekt](https://lore.kernel.org/git/pull.1820.v3.git.1738602667.gitgitgadget@gmail.com/) wurde von [Derrick Stolee](https://stolee.dev/) geleitet und mit [e565f37553](https://gitlab.com/gitlab-org/git/-/commit/e565f3755342caf1d21e22359eaf09ec11d8c0ae) zusammengeführt.\n\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n\n## Einführung von zlib-ng\n\n\nAlle Objekte im Ordner `.git/` werden von Git mit [`zlib`](https://zlib.net/) komprimiert. `zlib` ist die Referenzimplementierung für das [RFC-1950-Format](https://datatracker.ietf.org/doc/html/rfc1950): ZLIB Compressed Data Format. `zlib` wurde 1995 entwickelt, hat eine lange Geschichte und ist unglaublich portabel, denn es unterstützt sogar viele Systeme, die älter als das Internet sind. Dank der breiten Unterstützung von Architekturen und Compilern ist es jedoch in seinen Fähigkeiten eingeschränkt.\n\n\nDer Fork [`zlib-ng`](https://github.com/zlib-ng/zlib-ng) wurde erstellt, um auf diese Einschränkungen einzugehen, denn `zlib-ng` ist für moderne Systeme optimiert. Dieser Fork verzichtet auf die Unterstützung von Legacy-Systemen und bietet stattdessen Patches für Intel-Optimierungen, einige Cloudflare-Optimierungen sowie mehrere kleinere Patches.\n\n\nDie Bibliothek `zlib-ng` selbst bietet einen Kompatibilitätslayer für `zlib`. Der Kompatibilitätslayer macht es möglich, dass `zlib-ng` ein Drop-in-Ersatz für `zlib` ist, ist jedoch nicht auf allen Linux-Distributionen verfügbar. In Git 2.49 gibt es folgende Neuerungen:\n\n\n- Ein Kompatibilitätslayer wurde zum Git-Projekt hinzugefügt.\n\n- Build-Optionen wurden sowohl zur Datei [`Makefile`](https://gitlab.com/gitlab-org/git/-/blob/b9d6f64393275b505937a8621a6cc4875adde8e0/Makefile#L186-187) als auch zur [Meson-Build-Datei](https://gitlab.com/gitlab-org/git/-/blob/b9d6f64393275b505937a8621a6cc4875adde8e0/meson.build#L795-811) hinzugefügt.\n\n\nMit diesen Ergänzungen kann man einfacher von der verbesserten Performance von `zlib-ng` profitieren.\n\n\nIn lokalen Benchmark konnte die Geschwindigkeit um rund 25 % gesteigert werden, wenn `zlib-ng` anstelle von `zlib` verwendet wurde. Wir sind dabei, diese Änderungen auch für GitLab.com auszurollen.\n\n\nWenn du von den Vorteilen von `zlib-ng` profitieren möchtest, überprüfe zuerst, ob Git auf deinem Gerät bereits `zlib-ng` verwendet, indem du `git version --build-options` ausführst:\n\n\n```shell\n\n$ git version --build-options\n\ngit version 2.47.1\n\ncpu: x86_64\n\nno commit associated with this build\n\nsizeof-long: 8\n\nsizeof-size_t: 8\n\nshell-path: /bin/sh\n\nlibcurl: 8.6.0\n\nOpenSSL: OpenSSL 3.2.2 4 Jun 2024\n\nzlib: 1.3.1.zlib-ng\n\n```\n\n\nWenn die letzte Zeile `zlib-ng` enthält, verwendet dein Git bereits die schnellere Variante von `zlib`. Wenn nicht, kannst du folgendermaßen vorgehen:\n\n\n- Bitte den/die Betreuer(in) des Git-Pakets, das du verwendest, die Unterstützung für `zlib-ng` hinzuzufügen; oder\n\n- Erstelle Git selbst aus der Quelle.\n\n\nDiese [Änderungen](https://gitlab.com/gitlab-org/git/-/commit/9d0e81e2ae3bd7f6d8a655be53c2396d7af3d2b0) wurden von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) [eingeführt](https://lore.kernel.org/git/20250128-b4-pks-compat-drop-uncompress2-v4-0-129bc36ae8f5@pks.im/).\n\n\n## Weitere Iteration auf Meson\n\n\nIn unserem Artikel über die Git-Version 2.48 haben wir über [die Einführung des Meson-Build-Systems](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-48-0/#meson-build-system) gesprochen. [Meson](https://de.wikipedia.org/wiki/Meson_(Build-System)) ist ein Tool für die Build-Automatisierung, das vom Git-Projekt genutzt wird und irgendwann [Autoconf](https://de.wikipedia.org/wiki/GNU_Build_System#GNU_Autoconf),\n\n[CMake](https://de.wikipedia.org/wiki/CMake) und sogar [Make](https://de.wikipedia.org/wiki/Make) ersetzen könnte.\n\n\nIn diesem Release-Zyklus wurde weiter an der Nutzung von Meson gearbeitet und es wurden verschiedene fehlende Funktionen und Fixes zur Stabilisierung eingeführt:\n\n\n- Die [verbesserte Testabdeckung für CI](https://lore.kernel.org/git/20250122-b4-pks-meson-additions-v3-0-5a51eb5d3dcd@pks.im/) wurde in [72f1ddfbc9](https://gitlab.com/gitlab-org/git/-/commit/72f1ddfbc95b47c6011bb423e6947418d1d72709) zusammengeführt.\n  - [Einzelne Elemente für die Nutzung von Meson in `contrib/`](https://lore.kernel.org/git/20250219-b4-pks-meson-contrib-v2-0-1ba5d7fde0b9@pks.im/) wurden in [2a1530a953](https://gitlab.com/gitlab-org/git/-/commit/2a1530a953cc4d2ae62416db86c545c7ccb73ace) zusammengeführt.\n  - [Verschiedene Fixes und Verbesserungen für das Build-Verfahren basierend auf Meson](https://lore.kernel.org/git/20250226-b4-pks-meson-improvements-v3-0-60c77cf673ae@pks.im/) wurden in [ab09eddf60](https://gitlab.com/gitlab-org/git/-/commit/ab09eddf601501290b5c719574fbe6c02314631f) zusammengeführt.\n  - [Meson wurde auf die Erstellung von `git-subtree(1)` aufmerksam gemacht](https://lore.kernel.org/git/20250117-b4-pks-build-subtree-v1-0-03c2ed6cc42e@pks.im/), was in [3ddeb7f337](https://gitlab.com/gitlab-org/git/-/commit/3ddeb7f3373ae0e309d9df62ada24375afa456c7) zusammengeführt wurde.\n  - [Die Dokumentationsseite für die Einführung in Meson, um HTML zu erzeugen](https://lore.kernel.org/git/20241227-b4-pks-meson-docs-v2-0-f61e63edbfa1@pks.im/) wurde in [1b4e9a5f8b](https://gitlab.com/gitlab-org/git/-/commit/1b4e9a5f8b5f048972c21fe8acafe0404096f694) zusammengeführt.\n\nAll diese Bemühungen wurden von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) durchgeführt.\n\n\n## Einstellung von .git/branches/ und .git/remotes/\n\n\nDu weißt wahrscheinlich, dass das Verzeichnis `.git` existiert und was es enthält. Hast du aber schon einmal von den Unterverzeichnissen `.git/branches/` und `.git/remotes/` gehört? Wie du vielleicht weißt, werden Referenzen auf Branches in `.git/refs/heads/` gespeichert. Wozu dienen also `.git/branches/` und `.git/remotes/`?\n\n\nBereits 2005 wurde [`.git/branches/`](https://git-scm.com/docs/git-fetch#_named_file_in_git_dirbranches) eingeführt, um Kurznamen für ein Remote zu speichern. Wenige Monate später wurden diese zu [`.git/remotes/`](https://git-scm.com/docs/git-fetch#_named_file_in_git_dirremotes) verschoben.\n\nIm Jahr [2006](https://lore.kernel.org/git/Pine.LNX.4.63.0604301520460.2646@wbgn013.biozentrum.uni-wuerzburg.de/) lernte [`git-config(1)`](https://git-scm.com/docs/git-config), [Remotes](https://git-scm.com/docs/git-config#Documentation/git-config.txt-remoteltnamegturl) zu speichern.\n\nDies wurde zur Standardmethode, um Remotes zu konfigurieren. 2011 wurden die Verzeichnisse `.git/branches/` and `.git/remotes/` als veraltet [dokumentiert](https://gitlab.com/git-scm/git/-/commit/3d3d282146e13f2d7f055ad056956fd8e5d7ed29#e615263aaf131d42be8b0d0888ebd3fec954c6c9_132_124) und nicht mehr in modernen Repositories verwendet.\n\n\nIm Jahr 2024 wurde das Dokument [BreakingChanges](https://git-scm.com/docs/BreakingChanges) angelegt, um grundlegende Änderungen für die nächste große Git-Version (v3.0) darzulegen. Diese Release ist zwar in nächster Zeit nicht geplant, doch in diesem Dokument werden Änderungen dokumentiert, die wahrscheinlich Teil dieser kommenden Release sind.\n\nIn [8ccc75c245](https://gitlab.com/git-scm/git/-/commit/8ccc75c2452b5814d2445d60d54266293ca48674) wurde die Verwendung der Verzeichnisse `.git/branches/` und `.git/remotes/` zu diesem Dokument hinzugefügt, wodurch sie offiziell als veraltet gelten und in Version Git 3.0 nicht mehr enthalten sein werden.\n\n\nVielen Dank an [Patrick Steinhardt](https://gitlab.com/pks-gitlab), der [diese Einstellung formalisiert hat](https://lore.kernel.org/git/20250122-pks-remote-branches-deprecation-v4-5-5cbf5b28afd5@pks.im/).\n\n\n## Rust-Datenbindungen für libgit\n\n\nBeim Kompilieren von Git wird die interne Bibliothek `libgit.a` erstellt. Diese Bibliothek enthält einige Kernfunktionen von Git.\n\n\nDiese Bibliothek ist (wie der Großteil von Git) zwar in C geschrieben, in Git 2.49 wurden jedoch Datenbindungen hinzugefügt, damit einige dieser Funktionen auch in Rust zur Verfügung stehen. Dazu wurden zwei neue Cargo-Pakete erstellt: `libgit-sys` und `libgit-rs`. Diese Pakete befinden sich im Unterverzeichnis [`contrib/`](https://gitlab.com/gitlab-org/git/-/tree/master/contrib) im Git-Quellbaum.\n\n\nEs ist [üblich](https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages), eine Bibliothek in zwei Pakete zu unterteilen, wenn ein [Foreign Function Interface](https://en.wikipedia.org/wiki/Foreign_function_interface) verwendet wird.\n\nDas Paket `libgit-sys` bietet die reine Schnittstelle zu C-Funktionen und verknüpft zur nativen Bibliothek `libgit.a`. Das Paket `libgit-rs` bietet eine Schnittstelle zu den Funktionen in `libgit-sys` mit einem für Rust typischen Gefühl.\n\n\nBisher ist die Funktionalität in diesen Rust-Paketen sehr begrenzt. Es wird nur eine Schnittstelle zur Interaktion mit `git-config(1)` geboten.\n\n\nDiese Initiative wurde von [Josh Steadmon](https://lore.kernel.org/git/8793ff64a7f6c4c04dd03b71162a85849feda944.1738187176.git.steadmon@google.com/) geleitet und mit [a4af0b6288](https://gitlab.com/gitlab-org/git/-/commit/a4af0b6288e25eb327ae9018cee09def9e43f1cd) zusammengeführt.\n\n\n## Neuer Namenshashing-Algorithmus\n\n\nDie Git-Objektdatenbank in `.git/` speichert die meisten ihrer Daten in Paketierungsdateien. Packfiles wurden verwendet, um Objekte über Kabel zwischen dem Git-Server und dem Client zu übertragen.\n\n\nAlles über das Format erfährst du unter [`gitformat-pack(5)`](https://git-scm.com/docs/gitformat-pack). Ein wichtiger Aspekt der Paketierungsdateien ist die Delta-Komprimierung. Bei der Delta-Komprimierung wird nicht jedes Objekt so gespeichert, wie es ist, sondern manche Objekte werden als _delta_ einer anderen _base_ gespeichert. Anstatt also den gesamten Inhalt der Objekte zu speichern, werden die Änderungen im Vergleich zu einem anderen Objekt gespeichert.\n\n\nOhne auf die Details einzugehen, wie diese Deltas berechnet oder gespeichert werden, kannst du dir vorstellen, dass es wichtig ist, sehr ähnliche Dateien zu gruppieren. In v2.48 und früheren Versionen verglich Git die letzten 16 Zeichen der Pfadnamen, um festzustellen, ob Blobs ähnlich sind. Dieser Algorithmus wird Version `1` genannt.\n\n\nAb Git 2.49 ist Version `2` verfügbar. Dies ist eine Iteration von Version `1`, jedoch so verändert, dass die Auswirkungen des übergeordneten Verzeichnisses reduziert werden. Du kannst die Version des Namenshashing-Algorithmus, die du verwenden möchtest, mit der Option `--name-hash-version` von [`git-repack(1)`](https://git-scm.com/docs/git-repack) festlegen.\n\n\n[Derrick Stolee](https://stolee.dev/), der dieses Projekt vorangetrieben hat, verglich die resultierende Größe der Paketierungsdateien, nachdem er `git repack -adf --name-hash-version=\u003Cn>` ausgeführt hatte:\n\n\n| Repository                                          \t| Größe Version 1   | Größe Version 2 |\n\n|---------------------------------------------------|-----------|---------|\n\n| [fluentui](https://github.com/microsoft/fluentui) | 440 MB \t| 161 MB   |\n\n| Repository B                                        \t| 6.248 MB   | 856 MB   |\n\n| Repository C                                        \t| 37.278 MB  | 6.921 MB |\n\n| Repository D                                        \t| 131.204 MB | 7.463 MB |\n\n\nWeitere Details findest du im [Patch-Set](https://lore.kernel.org/git/pull.1823.v4.git.1738004554.gitgitgadget@gmail.com/), das in [aae91a86fb](https://gitlab.com/gitlab-org/git/-/commit/aae91a86fb2a71ff89a71b63ccec3a947b26ca51) zusammengeführt wurde.\n\n\n## Promisor-Remote-Fähigkeit\n\n\nEs ist bekannt, dass Git nicht gut mit großen Dateien umgehen kann. Es gibt einige Lösungen für dieses Problem wie [Git LFS](https://git-lfs.com/), die jedoch immer noch Mängel aufweisen. Einige davon sind Folgende:\n\n\n- Mit Git LFS muss der/die Benutzer(in) konfigurieren, welche Dateien in den LFS kommen sollen. Der Server hat keine Kontrolle darüber und muss alle Dateien bereitstellen.\n\n- Wenn eine Datei ins Repository committet wird, gibt es keine Möglichkeit, sie wieder herauszuholen, ohne den Verlauf neu zu schreiben. Das ist vor allem bei großen Dateien ärgerlich, da sie dadurch für immer dort festhängen.\n\n- Benutzer(innen) können nicht ändern, welche Dateien im Git LFS abgelegt werden sollen.\n\n- Es ist schwierig, ein Tool wie Git LFS richtig einzurichten, den Umgang damit zu erlernen und es zu nutzen.\n\n\nSeit einiger Zeit verfügt Git über das Konzept der Promisor Remotes. Diese Funktion kann für große Dateien genutzt werden und wurde in Git 2.49 noch einen Schritt weiterentwickelt.\n\n\nDie Idee hinter der neuen Promisor-Remote-Fähigkeit ist relativ einfach: Anstatt alle Objekte selbst zu senden, kann ein Git-Server dem Git-Client sagen: „Lade diese Objekte von _XYZ_ herunter.“ _XYZ_ ist der Promisor Remote.\n\n\nGit 2.49 ermöglicht es dem Server, die Informationen des Promisor Remote an den Client weiterzugeben. Diese Änderung ist eine Erweiterung von [`gitprotocol-v2`](https://git-scm.com/docs/gitprotocol-v2). Während der Server und der Client Daten hin und her übertragen, kann der Server Namen und URLs der Promisor Remotes senden, die er kennt.\n\n\nDerzeit verwendet der Client die Promisor-Remote-Infos, die er vom Server während des Klonens erhält, nicht, sodass weiterhin alle Objekte vom Remote zu dem Klon übermittelt werden, von dem aus der Vorgang initiiert wurde. Wir planen, diese Funktion weiter zu verbessern, sodass die Promisor-Remote-Info vom Server genutzt werden kann und die Funktion benutzerfreundlicher wird.\n\n\nDieses [Patch-Set](https://lore.kernel.org/git/20250218113204.2847463-1-christian.couder@gmail.com/) wurde von [Christian Couder](https://gitlab.com/chriscool) eingereicht und mit [2c6fd30198](https://gitlab.com/gitlab-org/git/-/commit/2c6fd30198187c928cbf927802556908c381799c) zusammengeführt.\n\n\n## Flacher Klon mit `--revision`\n\n\nDie neue Option `--revision` wurde zu [`git-clone(1)`](https://git-scm.com/docs/git-clone/de) hinzugefügt. Auf diese Weise kannst du einen flachen Klon eines Repository erstellen, der nur den Verlauf der jeweiligen Revision enthält. Die Option ist ähnlich wie `--branch`, akzeptiert aber einen ref-Namen (wie `refs/heads/main`, `refs/tags/v1.0` und `refs/merge-requests/123`) oder eine hexadezimale Commit-Objekt-ID. Der Unterschied zu `--branch` ist, dass kein Tracking-Branch erstellt und `HEAD` abgetrennt wird. Diese Option ist also nicht geeignet, wenn du wieder zu diesem Branch beitragen möchtest.\n\n\nDu kannst `--revision` in Kombination mit `--depth` verwenden, um einen minimalen Klon zu erstellen. Ein vorgeschlagener Anwendungsfall ist das automatisierte Testen. Wenn du ein CI-System hast, bei dem ein Branch (oder eine beliebige Referenz) ausgecheckt werden muss, um autonome Tests am Quellcode durchzuführen, brauchst du nur einen minimalen Klon.\n\n\nDiese [Änderung](https://gitlab.com/gitlab-org/git/-/commit/5785d9143bcb3ef19452a83bc2e870ff3d5ed95a) wurde von [Toon Claes](https://gitlab.com/toon) [vorangetrieben](https://lore.kernel.org/git/20250206-toon-clone-refs-v7-0-4622b7392202@iotcl.com/).\n\n\n# Mehr erfahren\n\n- [Was gibt es Neues in Git 2.48.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-48-0/)\n\n- [Was gibt es Neues neu in Git 2.47.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-47-0/)\n\n- [Was gibt es Neues in Git 2.46.0?](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-46-0/)\n",[991],"Toon Claes","2025-04-08","2025-03-14","Was gibt es Neues in Git 2.49.0?",[269,681,9],{"slug":997,"featured":90,"template":685},"whats-new-in-git-2-49-0","content:de-de:blog:whats-new-in-git-2-49-0.yml","Whats New In Git 2 49 0","de-de/blog/whats-new-in-git-2-49-0.yml","de-de/blog/whats-new-in-git-2-49-0",{"_path":1003,"_dir":246,"_draft":6,"_partial":6,"_locale":7,"seo":1004,"content":1010,"config":1015,"_id":1017,"_type":13,"title":1018,"_source":15,"_file":1019,"_stem":1020,"_extension":18},"/de-de/blog/a-beginners-guide-to-the-git-reftable-format",{"ogTitle":1005,"schema":1006,"ogImage":1007,"ogDescription":1008,"ogSiteName":671,"noIndex":6,"ogType":672,"ogUrl":1009,"title":1005,"canonicalUrls":1009,"description":1008},"Der Anfängerleitfaden zum „reftable“-Format von Git","                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Der Anfängerleitfaden zum „reftable“-Format von Git\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Patrick Steinhardt\"}],\n        \"datePublished\": \"2024-05-30\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664595/Blog/Hero%20Images/blog-image-template-1800x945__9_.png","In Git 2.45.0 hat GitLab das reftable Backend in Git eingeführt – dies verändert die Art und Weise, wie Referenzen gespeichert werden, von Grund auf. Erhalte detaillierte Einblicke, wie dieses neue Format funktioniert.","https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format",{"heroImage":1007,"body":1011,"authors":1012,"updatedDate":931,"date":1013,"title":1005,"tags":1014,"description":1008,"category":679},"Bis vor Kurzem war das „files“-Format die einzige Möglichkeit in Git,\nReferenzen zu speichern. Mit der [Version\nGit 2.45.0](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-45-0/)\nkann Git nun Referenzen im „reftable“-Format speichern. Dieses neue Format\nist ein Binärformat, das deutlich komplexer als das alte “files” Format ist.\nDiese Komplexität ermöglicht es jedoch, einige Mängel des „files“-Formats zu\nbeheben. Die Entwicklungsziele des „reftable“-Formats sind unter anderem\nfolgende:\n\n\n- Die Suche nach einzelnen Referenzen und die Iterationen über zahlreichen Referenzen soll so effizient und schnell wie möglich sein.\n\n- Das konsistente Lesen von Referenzen soll unterstützt werden, sodass Git nie einen Zwischenzustand liest, wenn ein Update an mehreren Referenzen nur teilweise angewendet wurde.\n\n- Atomares Schreiben soll unterstützt werden, sodass die Aktualisierung von mehreren Referenzen nur entweder vollständig oder gar nicht möglich ist.\n\n- Effiziente Speicherung von Referenzen und Reflog-Einträgen.\n\n\nIn diesem Artikel kommen wir allen Feinheiten des „reftable“-Formats auf die Schliche und sehen uns genau an, wie es funktioniert.\n\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n\n## So speichert Git Referenzen\n\n\nBevor wir uns die Details des „reftable“-Formats ansehen, fassen wir nochmals kurz zusammen, wie Git in der Vergangenheit Referenzen gespeichert hat. Wenn du damit bereits vertraut bist, kannst du gleich zum nächsten Abschnitt springen.\n\n\nEin Git-Repository enthält zwei wesentliche Datenstrukturen:\n\n\n- [Objekte](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects), die die eigentlichen Daten deines Repositorys enthalten. Dazu gehören Commits, die Verzeichnisstruktur und die Blobs, die deinen Quellcode enthalten. Objekte verweisen aufeinander und bilden so einen Objektgraphen. Außerdem hat jedes Objekt eine Objekt-ID, durch die es eindeutig identifiziert wird.\n\n\n- Referenzen wie Branches und Tags sind Wegweiser im Objektgraphen, sodass du Objekten Namen geben kannst, die einfacher zu merken sind, und verschiedene Wege deines Entwicklungsverlaufs nachverfolgen kannst. Ein Repository kann zum Beispiel einen `main`-Branch enthalten, der eine Referenz mit dem Namen `refs/heads/main` ist und auf einen bestimmten Commit zeigt.\n\n\nReferenzen werden in der Referenzdatenbank gespeichert. Bis Git 2.45.0 gab es nur das Datenbankformat „files“. In diesem Format wird jede Referenz als einfache Datei gespeichert, die eines der folgenden Elemente enthält:\n\n\n- Eine normale Referenz, die die Objekt-ID des Commits enthält, auf den sie zeigt.\n\n- Eine symbolische Referenz, die den Namen einer anderen Referenz enthält. Dies ist ähnlich wie ein symbolischer Link, der auf eine andere Datei zeigt.\n\n\nIn regelmäßigen Abständen werden diese Referenzen in eine einzige `packed-refs`-Datei komprimiert, damit Referenzen effizienter durchsucht werden können.\n\n\nDie folgenden Beispiele sollen eine Vorstellung davon geben, wie das „files“-Format funktioniert:\n\n\n```shell\n\n$ git init .\n\n$ git commit --allow-empty --message \"Initial commit\"\n\n[main (root-commit) 6917c17] Initial commit\n\n\n# HEAD ist eine symbolische Referenz, die auf refs/heads/main zeigt.\n\n$ cat .git/HEAD\n\nref: refs/heads/main\n\n\n# refs/heads/main ist eine normal Referenz, die auf einen Commit zeigt.\n\n$ cat .git/refs/heads/main\n\n6917c178cfc3c50215a82cf959204e9934af24c8\n\n\n# git-pack-refs(1) komprimiert diese Referenzen in eine packed-refs Datei.\n\n$ git pack-refs --all\n\n$ cat .git/packed-refs\n\n# pack-refs with: peeled fully-peeled sorted\n\n6917c178cfc3c50215a82cf959204e9934af24c8 refs/heads/main\n\n```\n\n\n## Hochrangige Struktur von reftables\n\n\nWenn du nun Git 2.45.0 oder eine neuere Version installiert hast, kannst du ein Repository mit dem „reftable“-Format erstellen, indem du den Switch `--ref-format=reftable` verwendest:\n\n\n```shell\n\n$ git init --ref-format=reftable .Initialized empty Git repository in /tmp/repo/.git/\n\n$ git rev-parse --show-ref-format\n\nreftable\n\n\n# Irrelevante Dateien wurden für ein einfacheres Verständnis entfernt.\n\n$ tree .git\n\n.git\n\n├── config\n\n├── HEAD\n\n├── index\n\n├── objects\n\n├── refs\n\n│   └── heads\n\n└── reftable\n  ├── 0x000000000001-0x000000000002-40a482a9.ref\n  └── tables.list\n\n4 directories, 6 files\n\n```\n\n\nSieh dir zunächst die Repository-Konfiguration an. Du wirst feststellen, dass sie den Schlüssel `extension.refstorage` enthält:\n\n\n```shell\n\n$ cat .git/config\n\n[core]\n    repositoryformatversion = 1\n    filemode = true\n    bare = false\n    logallrefupdates = true\n[extensions]\n    refstorage = reftable\n```\n\n\nDiese Konfiguration teilt Git mit, dass das Repository mit dem „reftable“-Format initialisiert wurde und gibt an, dass Git das „reftable“-Backend nutzen muss, um darauf zuzugreifen.\n\n\nSeltsamerweise enthält das Repository immer noch einige Dateien, die aussehen, als würde das „files“-Backend verwendet werden:\n\n\n- `HEAD` würde normalerweise eine symbolische Referenz sein, die auf deinen derzeit ausgecheckten Branch zeigt. Obwohl es nicht vom „reftable“-Backend verwendet wird, ist es für Git-Clients erforderlich, um das Verzeichnis als Git-Verzeichnis zu erkennen. Wenn du also das „reftable“-Format verwendest, ist `HEAD` ein Stub mit dem Inhalt `ref: refs/heads/.invalid`.\n\n\n- `refs/heads` ist eine Datei mit dem Inhalt `this repository uses the reftable format`. Git-Clients, die das Format „reftable“ nicht kennen, würden normalerweise erwarten, dass dieser Pfad ein Verzeichnis ist. Wenn du also diesen Pfad bewusst als Datei erstellst, führt dies dazu, dass ältere Git-Clients fehlschlagen, wenn sie versuchen, mit dem „files“-Backend auf das Repository zuzugreifen.\n\n\nDie tatsächlichen Referenzen werden im Verzeichnis `reftable/` gespeichert:\n\n\n```shell\n\n$ tree .git/reftable\n\n.git/reftable/\n\n├──0x000000000001-0x000000000001-794bd722.ref\n\n└── tables.list\n\n\n$ cat .git/reftable/tables.list\n\n0x000000000001-0x000000000001-794bd722.ref\n\n```\n\n\nEs gibt hier zwei Dateien:\n\n\n- `0x000000000001-0x000000000001-794bd722.ref` ist eine Tabelle mit Referenzen und den Reflog-Einträgen in einem Binärformat.\n\n\n- `tables.list` ist eine Liste von Tabellen. Im aktuellen Status des Repositorys enthält die Datei eine Zeile, die der Name der Tabelle ist. Diese Datei verfolgt den aktuellen Satz aktiver Tabellen in der „reftable“-Datenbank und wird aktualisiert, wenn neue Tabellen zum Repository hinzugefügt werden.\n\n\nWenn du eine Referenz aktualisierst, wird eine neue Tabelle erstellt:\n\n\n```shell\n\n$ git commit --allow-empty --message \"Initial commit\"\n\n[main (root-commit) 1472a58] Initial commit\n\n\n$ tree .git/reftable\n\n.git/reftable/\n\n├──0x000000000001-0x000000000002-eb87d12b.ref\n\n└── tables.list\n\n\n$ cat .git/reftable/tables.list\n\n0x000000000001-0x000000000002-eb87d12b.ref\n\n```\n\n\nWie du sehen kannst, wurde die vorherige Tabelle durch eine neue ersetzt. Darüber hinaus wurde die Datei `tables.list` aktualisiert und enthält nun die neue Tabelle.\n\n\n## Die Struktur einer Tabelle\n\n\nWie bereits erwähnt, sind die eigentlichen Daten der Referenzdatenbank in Tabellen enthalten. Grob gesagt ist eine Tabelle in mehrere Abschnitte unterteilt:\n\n\n- Der „Header“ enthält Metadaten zur Tabelle. Dazu gehören unter anderem die Version des Formats, die Blockgröße und die vom Repository verwendete Hash-Funktion (z. B. SHA1 oder SHA256).\n\n- Der Abschnitt „Ref“ enthält deine Referenzen. Diese Datensätze haben einen Schlüssel, der dem Referenznamen entspricht und entweder auf eine Objekt-ID für reguläre Referenzen oder auf eine andere Referenz für symbolische Referenzen zeigt.\n\n- Der Abschnitt „Obj“ enthält die umgekehrte Zuordnung von Objekt-IDs zu den Referenzen, die auf diese Objekt-IDs zeigen. Diese ermöglichen es Git, effizient zu suchen, welche Referenzen auf eine bestimmte Objekt-ID zeigen.\n\n- Der Abschnitt „Log“ enthält deine Reflog-Einträge. Diese Datensätze haben einen Schlüssel, der dem Referenznamen entspricht, sowie einen Index, der die Nummer des Reflog-Eintrags darstellt. Außerdem enthalten sie die alten und neuen Objekt-IDs sowie die Nachricht für diesen Reflog-Eintrag.\n\n- Der „Footer“ enthält Zeiger zu den verschiedenen Abschnitten.\n\n\n![Lange Tabelle mit allen reftable-Abschnitten](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_1_-_Reftable_overview.svg)\n\n\nDie Abschnittstypen sind alle ähnlich strukturiert. Abschnitte enthalten eine Reihe von Datensätzen, die nach den Schlüsseln der einzelnen Datensätze sortiert sind. Wenn du zum Beispiel zwei Ref-Datensätze `refs/heads/aaaaa` und `refs/heads/bbb` hast, hast du zwei Ref-Datensätze mit diesen Referenznamen als jeweiligen Schlüssel, weshalb `refs/heads/aaaaa` vor `refs/heads/bbb` kommt.\n\n\nDarüber hinaus ist jeder Abschnitt in Blöcke mit einer festen Länge unterteilt. Diese Blocklänge ist im Header codiert und dient zwei Zwecken:\n\n\n- Da sie den Anfang des Abschnitts markieren und die Blockgröße angeben, weiß der bzw. die Leser(in) implizit, wo jeder der Blöcke beginnt. Dadurch kann Git gleich in die Mitte des Abschnitts springen, ohne vorherige Blocks lesen zu müssen. So kann die binäre Suche in Blöcken das Durchsuchen von Datensätzen beschleunigen.\n\n- Sie stellt sicher, dass Git weiß, wie viele Daten gleichzeitig von der Festplatte gelesen werden sollen. Folglich ist die Blockgröße standardmäßig auf 4 KiB eingestellt, was die häufigste Sektorgröße für Festplatten ist. Die maximale Blockgröße beträgt 16 MB.\n\n\nWenn wir zum Beispiel in einen „ref“-Abschnitt schauen, sieht er ungefähr wie die folgende Grafik aus. Achte darauf, wie die Datensätze lexikografisch in den Blocks, aber auch blockübergreifend sortiert sind.\n\n\n![Referenzblock, nicht komprimiert](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_2_-_Ref_block_uncompressed.svg)\n\n\nMit diesem Wissen können wir nun einen Datensatz finden, indem wir die folgenden Schritte befolgen:\n\n\n1. Führe eine Binärsuche über die Blocks durch, indem du dir die Schlüssel der jeweiligen ersten Datensätze ansiehst und den Block identifizierst, der unseren Datensatz enthalten muss.\n\n\n2. Führe eine lineare Suche in den Datensätzen dieses Blocks durch.\n\n\nBeide Schritte sind immer noch recht ineffizient. Wenn wir viele Blöcke haben, müssen wir logarithmisch viele davon in unserer Binärsuche lesen, um den gewünschten Block zu finden. Und wenn Blöcke viele Datensätze enthalten, müssen wir vielleicht bei der linearen Suche alle davon lesen.\n\n\nDas „reftable“-Format verfügt über zusätzliche integrierte Mechanismen, um diese Leistungsbedenken auszuräumen. Wir gehen in den nächsten Abschnitten darauf ein.\n\n\n### Präfix-Komprimierung\n\n\nWie du vielleicht bemerkt hast, haben alle Datensatzschlüssel das gleiche Präfix `refs/`. Dies ist häufig so in Git:\n\n\n- Alle Branches beginnen mit `refs/heads/`.\n\n- Alle Tags beginnen mit `refs/tags/`.\n\n\nDaher gehen wir davon aus, dass nachfolgende Datensätze höchstwahrscheinlich einen signifikanten Anteil ihres Schlüssels gemeinsam haben. Dies ist eine gute Gelegenheit, um wertvollen Speicherplatz zu sparen. Da wir wissen, dass die meisten Schlüssel ein gemeinsames Präfix haben, ist es sinnvoll, dies zu optimieren.\n\n\nDie Optimierung verwendet Präfix-Komprimierung. Jeder Datensatz kodiert eine Präfixlänge, die den Leser(innen) mitteilt, wie viele Bytes des Schlüssels des vorhergehenden Datensatzes wiederverwendet werden sollen. Wenn wir zwei Datensätze haben, `refs/heads/a` und `refs/heads/b`, kann letzterer kodiert werden, indem man eine Präfixlänge von 11 angibt und dann nur das Suffix `b` speichert. Die Leser(innen) nehmen dann die ersten 11 Bytes von `refs/heads/a`, was `refs/heads/` ist, und fügen das Suffix `b` hinzu.\n\n\n![Präfix-Komprimierung](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_3_-_Ref_block_prefix_compression.svg)\n\n\n### Neustart-Punkte\n\n\nWie bereits erklärt, ist eine lineare Suche der beste Weg, mit unserem derzeitigen Wissen über das „reftable“-Format in einem Block nach einer Referenz zu suchen. Der Grund dafür ist, dass die Datensätze keine fixe Länge haben. Daher können wir nicht feststellen, wo Datensätze beginnen, ohne von Anfang an den Block zu durchsuchen. Auch wenn Datensätze eine fixe Länge hätten, könnten wir nicht in der Mitte eines Blocks suchen, da die Präfix-Kompression erfordert, dass wir auch die vorhergehenden Datensätze lesen.\n\n\nEine lineare Suche wäre ziemlich ineffizient, da Blöcke Hunderte oder sogar Tausende von Datensätzen enthalten können. Um dieses Problem zu beheben, codiert das „reftable“-Format sogenannte Neustart-Punkte in jeden Block. Neustart-Punkte sind unkomprimierte Datensätze, bei denen keine Präfix-Komprimierung verwendet wird. Folglich enthalten Datensätze an Neustart-Punkten immer ihren vollständigen Schlüssel, und es wird möglich, den Datensatz direkt zu suchen und zu lesen, ohne die vorhergehenden Datensätze lesen zu müssen. Diese Neustart-Punkte sind in der Fußzeile jedes Blocks aufgeführt.\n\n\nMit diesen Informationen können wir eine lineare Suche über den Block vermeiden. Stattdessen können wir jetzt eine Binärsuche über die Neustart-Punkte durchführen, bei der wir nach dem ersten Neustart-Punkt mit einem Schlüssel suchen, der lexikographisch größer ist als der gesuchte Schlüssel. Daraus folgt, dass sich der gewünschte Datensatz in dem Abschnitt befinden muss, der sich vom _vorhergehenden_ Neustart-Punkt bis zum identifizierten Neustart-Punkt erstreckt.\n\n\nDaher ist unser erstes Vorgehen bei der Suche nach einem Datensatz (Binärsuche nach dem Block, Linearsuche nach dem Datensatz) nun wie folgt:\n\n\n1. Führe eine Binärsuche über die Blocks durch und finde den Block, der unseren Datensatz enthalten muss.\n\n\n2. Führe eine Binärsuche über die Neustart-Punkte durch und identifiziere den Unterabschnitt des Blocks, der unseren Datensatz enthalten muss.\n\n\n3. Führe eine lineare Suche in den Datensätzen dieses Unterabschnitts.\n\n\n![Lineare Suche nach einem Datensatz](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_4_-_Restart_points.svg)\n\n\n### Indizes\n\n\nDie Suche nach Datensätzen in einem Block wäre nun einigermaßen effizient. Es ist aber weiterhin ineffizient, den Block selbst zu finden. Eine Binärsuche kann bei ein paar Blöcken funktionieren, aber Repositories mit Millionen von Referenzen können Hunderte oder sogar Tausende von Blöcken haben. Ohne zusätzliche Datenstruktur würde dies durchschnittlich logarithmisch viele Festplattenzugriffe verursachen.\n\nUm dies zu vermeiden, kann auf jeden Abschnitt ein Indexabschnitt folgen, der eine effiziente Möglichkeit bietet, einen Block nachzuschlagen. Jeder Indexdatensatz enthält die folgenden Informationen:\n\n\n- Die Position des Blocks, den er indiziert.\n\n- Der Schlüssel des letzten Datensatzes des Blocks, den er indiziert.\n\n\nBei drei oder weniger Blöcken erfordert eine Binärsuche immer höchstens zwei Festplattenlesevorgänge, um den gewünschten Zielblock zu finden. Dies ist die gleiche Anzahl von Lesevorgängen, die wir mit einem Index hätten: einen, um den Index selbst zu lesen, und einen, um den gewünschten Block zu lesen. Folglich werden Indizes nur geschrieben, wenn sie tatsächlich einige Lesevorgänge einsparen würden, was ab vier indizierten Blöcken der Fall ist.\n\n\nNun stellt sich die Frage: Was passiert, wenn der Index selbst so groß wird, dass er sich über mehrere Blöcke erstreckt? Du hast es vielleicht erraten: Wir schreiben einen weiteren Index, der den Index indiziert. Diese mehrstufigen Indizes werden erst dann wirklich notwendig, wenn du Repositories mit hunderttausenden von Referenzen hast.\n\n\nMit diesen Indizes können wir jetzt das Verfahren zum Nachschlagen von Datensätzen noch effizienter machen:\n\n1. Finde heraus, ob es einen Index gibt, indem du dir die Fußzeile der Tabelle ansiehst.\n  - Wenn es einen gibt, führe eine Binärsuche über den Index durch, um den gewünschten Block zu finden. Dieser Block kann selbst auf einen Indexblock verweisen. In diesem Fall müssen wir diesen Schritt wiederholen, bis wir einen Datensatz des gewünschten Typs finden.\n  - Ansonsten führe eine Binärsuche über die Blöcke durch, wie wir es zuvor getan haben.\n2. Führe eine Binärsuche über die Neustart-Punkte durch und identifiziere den Unterabschnitt des Blocks, der unseren Datensatz enthalten muss.\n\n3. Führe eine lineare Suche in den Datensätzen dieses Unterabschnitts durch.\n\n\n## Mehrere Tabellen\n\n\nBis jetzt haben wir nur besprochen, wie man eine _einzelne_ Tabelle liest. Aber wie der Name `tables.list` schon sagt, kannst du tatsächlich eine Liste von Tabellen in deiner „reftable“-Datenbank haben.\n\n\nJedes Mal, wenn du eine Referenz in deinem Repository aktualisierst, wird eine neue Tabelle geschrieben und an `tables.list` angehängt. So hast du schließlich mehrere Tabellen:\n\n\n```Shell\n\n$ tree .git/reftable/\n\n.git/reftable/\n\n├──0x0000000000000001-0x000000000007-8dcd8a77.ref\n\n├── 0x000000000008-0x000000000008-30e0f6f6.ref\n\n└── tables.list\n\n\n$ cat .git/reftable/tables.list\n\n0x000000000001-0x000000000007-8dcd8a77.ref\n\n0x000000000008-0x000000000008-30e0f6f6.ref\n\n```\n\n\nUm den tatsächlichen Status eines Repositorys zu lesen, müssen wir diese mehreren Tabellen zu einer einzigen virtuellen Tabelle zusammenführen.\n\n\nDu fragst dich vielleicht: Wenn für jede Referenzaktualisierung eine Tabelle geschrieben wird und dieselbe Referenz mehrmals aktualisiert wird, woher kennt das „reftable“-Format den aktuellsten Wert einer bestimmten Referenz? Intuitiv könnte man davon ausgehen, dass der Wert derjenige aus der neuesten Tabelle ist, die die Referenz enthält.\n\n\nTatsächlich hat jeder einzelne Datensatz einen sogenannten Aktualisierungsindex, der die „Priorität“ eines Datensatzes kodiert. Wenn beispielsweise zwei Ref-Datensätze mit demselben Namen existieren, überschreibt derjenige mit dem höheren Aktualisierungsindex denjenigen mit dem niedrigeren Aktualisierungsindex.\n\n\nDiese Aktualisierungsindizes sind in der obigen Dateistruktur sichtbar. Die langen Hex-Zeichenfolgen (z. B. `0x000000000001`) sind die Aktualisierungsindizes, wobei die linke Seite des Tabellennamens der minimale Aktualisierungsindex ist, der in der Tabelle enthalten ist, und die rechte Seite der maximale Aktualisierungsindex ist.\n\n\nDas Zusammenführen der Tabellen erfolgt dann über eine [Vorrangwarteschlange](https://de.wikipedia.org/wiki/Vorrangwarteschlange), die nach dem Schlüssel des Ref-Datensatzes sowie dem Aktualisierungsindex geordnet ist. Angenommen, wir möchten alle Ref-Datensätze durchsuchen, würden wir wie folgt vorgehen:\n\n\n1. Füge für jede Tabelle ihren ersten Datensatz zur Vorrangwarteschlange hinzu.\n\n\n![Ersten Datensatz zur Vorrangwarteschlange hinzufügen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_5_-_Priority_queue_1.svg)\n\n\n2. Liefere den Kopf der Vorrangwarteschlange. Da die Warteschlange nach Aktualisierungsindex geordnet ist, muss sie die aktuellste Version sein. Füge das nächste Element aus dessen Tabelle zur Vorrangwarteschlange hinzu.\n\n\n![Head der Vorrangwarteschlange angeben](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_6_-_Priority_queue_2.svg)\n\n\n3. Ziehe alle Datensätze aus der Warteschlange, die den gleichen Namen haben. Diese Datensätze werden verschattet, was bedeutet, dass sie nicht angezeigt werden. Füge für jede Tabelle, für die wir Datensätze ablegen, den nächsten Datensatz zur Vorrangwarteschlange hinzu.\n\n\n![Alle Datensätze aus der Warteschlange ablegen, die den gleichen Namen haben](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_7_-_Priority_queue_3.svg)\n\n\nJetzt können wir bereinigen und den Vorgang wiederholen, um Datensätze für andere Schlüssel zu lesen.\n\n\nTabellen können spezielle „tombstone“-Datensätze enthalten, die einen Datensatz als gelöscht markieren. So können wir Datensätze löschen, ohne den jeweiligen Datensatz aus allen Tabellen löschen zu müssen.\n\n\n### Autokomprimierung\n\n\nWährend die Idee hinter der Vorrangwarteschlange zwar einfach ist, wäre es allerdings eher ineffizient, Hunderte oder sogar nur Dutzende von Tabellen auf diese Weise zusammenzuführen. Es stimmt, dass jede Aktualisierung an deinen Referenzen eine neue Tabelle an deine `tables.list`-Datei anhängt. Das ist jedoch nur ein Teil der Wahrheit.\n\n\nDer andere Teil ist die Autokomprimierung: Nachdem eine neue Tabelle an die Liste der Tabellen angehängt wurde, überprüft das „reftable“-Backend, ob manche der Tabellen zusammengeführt werden sollen. Dies erfolgt durch eine einfache Heuristik. Wir überprüfen, ob die Liste der Tabellen eine [geometrische Folge](https://de.wikipedia.org/wiki/Geometrische_Folge) der Dateigrößen bildet. Jede Tabelle `n` muss mindestens doppelt so groß sein wie die nächstletzte Tabelle `n + 1`. Wenn gegen diese geometrische Folge verstoßen wird, komprimiert das Backend die Tabellen, sodass die geometrische Folge wiederhergestellt wird.\n\n\nIm Laufe der Zeit führt dies zu Strukturen, die wie folgt aussehen:\n\n\n```Shell\n\n$ du --apparent-size .git/reftable/*\n\n429    .git/reftable/0x000000000001-0x00000000bd7c-d9819000.ref\n\n101    .git/reftable/0x00000000bd7d-0x00000000c5ac-c34b88a4.ref\n\n32    .git/reftable/0x00000000c5ad-0x00000000cc6c-60391f53.ref\n\n8    .git/reftable/0x00000000cc6d-0x00000000cdc1-61c30db1.ref\n\n3    .git/reftable/0x00000000cdc2-0x00000000ce67-d9b55a96.ref\n\n1    .git/reftable/0x00000000ce68-0x00000000ce6b-44721696.ref\n\n1    .git/reftable/tables.list\n\n```\n\n\nBeachte, wie für jede einzelne Tabelle die Eigenschaft `size(n) > size(n+1) * 2` gilt.\n\n\nEine der Folgen der Autokomprimierung ist, dass sich das „reftable“-Backend selbst erhält. Wir müssen somit nicht mehr den Befehl `git pack-refs` zum Optimieren der Referenzen ausführen.\n\n\n## Möchtest du mehr erfahren?\n\n\nDu solltest jetzt ein gutes Verständnis dafür haben, wie das neue „reftable“-Format im Detail funktioniert. Wenn du noch tiefer in das Format eintauchen möchtest, kannst du dir dessen [technische Dokumentation](https://git-scm.com/docs/reftable) des Git-Projekts ansehen.\n\n\n> Lies dir unsere [Zusammenfassung von Git 2.45.0](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/) durch, um herauszufinden, was sonst noch in dieser Version von Git auf dich wartet.\n",[676],"2024-05-30",[9,729,681,813],{"slug":1016,"featured":90,"template":685},"a-beginners-guide-to-the-git-reftable-format","content:de-de:blog:a-beginners-guide-to-the-git-reftable-format.yml","A Beginners Guide To The Git Reftable Format","de-de/blog/a-beginners-guide-to-the-git-reftable-format.yml","de-de/blog/a-beginners-guide-to-the-git-reftable-format",2,[664,690,714,737,757,779,801,821,844],1759347937318]