تعمل الأسماء المستعارة لـ Git بشكل مشابه للأسماء المستعارة العادية في الصدفة، ولكنها خاصة بأوامر Git. إنها تسمح لك بإنشاء اختصارات لأوامر أطول أو إنشاء أوامر جديدة غير متوفرة افتراضيًا.
تعمل الأسماء المستعارة في نفس بيئة الصدفة كأوامر git الأخرى، وتستخدم في الغالب لتبسيط سير العمل المشترك.
تستدعي الأسماء المستعارة البسيطة أمرًا Git واحدًا مع مجموعة من الوسائط. على سبيل المثال، يمكنك إنشاء اسم مستعار لإظهار حالة المستودع عن طريق تشغيل git Status بالاسم المستعار s:
[alias] s = status
يمكنك بعد ذلك تشغيل git s لإظهار حالة المستودع. نظرًا لأننا قمنا بتكوين الاسم المستعار في ~/.gitconfig، فهو متاح لجميع المستودعات الموجودة على النظام.
يمكنك أيضًا إنشاء أسماء مستعارة لـ git تقوم بتشغيل أمر shell عشوائي. للقيام بذلك، يجب أن يبدأ الاسم المستعار بـ !. هذا يخبر git بتنفيذ الاسم المستعار كما لو لم يكن أمرًا فرعيًا لـ git. على سبيل المثال، إذا أردت تشغيل أمرين git بالتسلسل، فيمكنك إنشاء اسم مستعار يقوم بتشغيل أمر shell:
[alias] my-alias = !git fetch && git rebase origin/master
يقوم هذا الاسم المستعار بتشغيل git fetch و git rebase Origin/main بالتسلسل عند تشغيل git my-alias.
أحد القيود على الأسماء المستعارة لـ git هو أنه لا يمكن تعيينها على قيمة متعددة الأسطر. وهذا يعني أنه بالنسبة للأسماء المستعارة الأكثر تعقيدًا، ستحتاج إلى تصغيرها.
بالإضافة إلى ذلك، في ملف INI أ؛ يتم استخدام الحرف للتعليق على بقية السطر. هذا يعني أنه لا يمكنك استخدام ; في أوامر الاسم المستعار الخاص بك.
قد يجعل هذان القيدان من الصعب إنشاء أسماء مستعارة أكثر تعقيدًا باستخدام بناء جملة الاسم المستعار لـ git القياسي، ولكن لا يزال من الممكن القيام بذلك. على سبيل المثال، قد يبدو الاسم المستعار الذي يستخدم if to Branch كما يلي:
[alias] branch-if = !bash -c "'!f() { if [ -z \"$1\" ]; then echo \"Usage: git branch-if\"; else git checkout -b $1; fi; }; f'"
تجعل هذه الحدود الأمر أكثر تعقيدًا لإنشاء وصيانة الأسماء المستعارة التي تحتوي على أي شكل من أشكال تدفق التحكم بداخلها. هذا هو المكان الذي تأتي فيه البرمجة النصية.
يمكنك كتابة gitalias باستخدام أي لغة برمجة تريدها. إذا كنت معتادًا على برمجة bash وترغب في استخدامها، فيمكنك إنشاء برنامج نصي bash يقوم بتشغيل أوامر git المطلوبة. الحقيقة هي أنني أقوى بكثير مع جافا سكريبت، لذلك هذا ما سأستخدمه.
إحدى المزايا الرئيسية الأخرى هي أنه باستخدام لغة البرمجة النصية، يمكن للأسماء المستعارة الخاصة بك أن تأخذ الوسائط وتعمل عليها بسهولة أكبر. سيقوم Git بإعادة توجيه أي وسيطات تمررها على واجهة سطر الأوامر (CLI) إلى الاسم المستعار الخاص بك عن طريق إلحاقها بنهاية الأمر. على هذا النحو، يجب أن يكون النص البرمجي الخاص بك قادرًا على قراءتها دون مشكلة. على سبيل المثال، في Node JS، يمكنك الوصول إلى الوسائط التي تم تمريرها إلى البرنامج النصي مباشرة علىprocess.argv.
لا تتغير الخطوات الأساسية لإعداد هذا بناءً على اللغة المختارة. ستحتاج إلى:
نحتاج إلى تحديث الاسم المستعار الخاص بنا للتحقق مما إذا كان الفرع رئيسيًا أم رئيسيًا ثم إعادة تحديد الفرع الصحيح. هذه حالة استخدام مثالية للبرنامج النصي.
#!/usr/bin/env node const { execSync } = require('child_process'); // We want to run some commands and not immediately fail if they fail function tryExec(command) { try { return { status: 0 stdout: execSync(command); } } catch (error) { return { status: error.status, stdout: error.stdout, stderr: error.stderr, } } } function getOriginRemoteName() { const { stdout, code } = tryExec("git remote", true); if (code !== 0) { throw new Error("Failed to get remote name. \n" stdout); } // If there is an upstream remote, use that, otherwise use origin return stdout.includes("upstream") ? "upstream" : "origin"; } // --verify returns code 0 if the branch exists, 1 if it does not const hasMain = tryExec('git show-ref --verify refs/heads/main').status === 0; // If main is present, we want to rebase main, otherwise rebase master const branch = hasMain ? 'main' : 'master'; const remote = getOriginRemoteName() // Updates the local branch with the latest changes from the remote execSync(`git fetch ${remote} ${branch}`, {stdio: 'inherit'}); // Rebases the current branch on top of the remote branch execSync(`git rebase ${remote}/${branch}`, {stdio: 'inherit'});حاليًا، لتشغيل البرنامج النصي، نحتاج إلى تشغيل العقدة ~/gitaliases/git-rebase-main.js. هذا ليس مثاليًا، وهو ليس شيئًا قد تعتاد على القيام به. يمكننا أن نجعل ذلك أسهل من خلال إنشاء اسم مستعار لـ git يقوم بتشغيل البرنامج النصي.
#!/usr/bin/env node const { execSync } = require('child_process'); // We want to run some commands and not immediately fail if they fail function tryExec(command) { try { return { status: 0 stdout: execSync(command); } } catch (error) { return { status: error.status, stdout: error.stdout, stderr: error.stderr, } } } function getOriginRemoteName() { const { stdout, code } = tryExec("git remote", true); if (code !== 0) { throw new Error("Failed to get remote name. \n" stdout); } // If there is an upstream remote, use that, otherwise use origin return stdout.includes("upstream") ? "upstream" : "origin"; } // --verify returns code 0 if the branch exists, 1 if it does not const hasMain = tryExec('git show-ref --verify refs/heads/main').status === 0; // If main is present, we want to rebase main, otherwise rebase master const branch = hasMain ? 'main' : 'master'; const remote = getOriginRemoteName() // Updates the local branch with the latest changes from the remote execSync(`git fetch ${remote} ${branch}`, {stdio: 'inherit'}); // Rebases the current branch on top of the remote branch execSync(`git rebase ${remote}/${branch}`, {stdio: 'inherit'});يمكنك الآن تشغيل git rebase-main لإعادة تحديد الفرع الصحيح، بغض النظر عما إذا كان رئيسيًا أو رئيسيًا.
دراسة حالة: تعديل
#!/usr/bin/env node const { execSync } = require('child_process'); // We want to run some commands and not immediately fail if they fail function tryExec(command) { try { return { status: 0 stdout: execSync(command); } } catch (error) { return { status: error.status, stdout: error.stdout, stderr: error.stderr, } } } function getOriginRemoteName() { const { stdout, code } = tryExec("git remote", true); if (code !== 0) { throw new Error("Failed to get remote name. \n" stdout); } // If there is an upstream remote, use that, otherwise use origin return stdout.includes("upstream") ? "upstream" : "origin"; } // --verify returns code 0 if the branch exists, 1 if it does not const hasMain = tryExec('git show-ref --verify refs/heads/main').status === 0; // If main is present, we want to rebase main, otherwise rebase master const branch = hasMain ? 'main' : 'master'; const remote = getOriginRemoteName() // Updates the local branch with the latest changes from the remote execSync(`git fetch ${remote} ${branch}`, {stdio: 'inherit'}); // Rebases the current branch on top of the remote branch execSync(`git rebase ${remote}/${branch}`, {stdio: 'inherit'});هذا البرنامج النصي أكثر تعقيدًا قليلاً من البرنامج الأخير، حيث يحتوي على بعض تدفق التحكم فيه. سوف يتحقق مما إذا كانت الفروع الأخرى تعتمد على الالتزام الحالي أم لا، وإذا كان الأمر كذلك فسيتم الخروج مع حدوث خطأ. وذلك لمنعك من تعديل الالتزام الذي تعتمد عليه الفروع الأخرى، لأن القيام بذلك قد يسبب مشاكل عند محاولة دمج أي فرع يعتمد على الالتزام.
لإعداد الاسم المستعار، يمكنك استخدام نفس الطريقة السابقة:
#!/usr/bin/env node const { execSync } = require('child_process'); // We want to run some commands and not immediately fail if they fail function tryExec(command) { try { return { status: 0 stdout: execSync(command); } } catch (error) { return { status: error.status, stdout: error.stdout, stderr: error.stderr, } } } function getOriginRemoteName() { const { stdout, code } = tryExec("git remote", true); if (code !== 0) { throw new Error("Failed to get remote name. \n" stdout); } // If there is an upstream remote, use that, otherwise use origin return stdout.includes("upstream") ? "upstream" : "origin"; } // --verify returns code 0 if the branch exists, 1 if it does not const hasMain = tryExec('git show-ref --verify refs/heads/main').status === 0; // If main is present, we want to rebase main, otherwise rebase master const branch = hasMain ? 'main' : 'master'; const remote = getOriginRemoteName() // Updates the local branch with the latest changes from the remote execSync(`git fetch ${remote} ${branch}`, {stdio: 'inherit'}); // Rebases the current branch on top of the remote branch execSync(`git rebase ${remote}/${branch}`, {stdio: 'inherit'});الآن يمكنك تشغيل git Adjust لتعديل الالتزام الأخير، أو git Adjust undo للتراجع عن التعديل الأخير. هذا هو البرنامج النصي الذي كتبته في البداية بشكل مضمن في gitconfig الخاص بي، ولكن مع تزايد تعقيده، قمت بنقله إلى ملف نصي. هذه طريقة رائعة لإدارة التعقيد في الأسماء المستعارة الخاصة بك. للمقارنة، هنا هو الاسم المستعار الأصلي:
#!/usr/bin/env node const { execSync } = require('child_process'); // We want to run some commands and not immediately fail if they fail function tryExec(command) { try { return { status: 0 stdout: execSync(command); } } catch (error) { return { status: error.status, stdout: error.stdout, stderr: error.stderr, } } } function getOriginRemoteName() { const { stdout, code } = tryExec("git remote", true); if (code !== 0) { throw new Error("Failed to get remote name. \n" stdout); } // If there is an upstream remote, use that, otherwise use origin return stdout.includes("upstream") ? "upstream" : "origin"; } // --verify returns code 0 if the branch exists, 1 if it does not const hasMain = tryExec('git show-ref --verify refs/heads/main').status === 0; // If main is present, we want to rebase main, otherwise rebase master const branch = hasMain ? 'main' : 'master'; const remote = getOriginRemoteName() // Updates the local branch with the latest changes from the remote execSync(`git fetch ${remote} ${branch}`, {stdio: 'inherit'}); // Rebases the current branch on top of the remote branch execSync(`git rebase ${remote}/${branch}`, {stdio: 'inherit'});كان من الممكن استخراج هذا البرنامج النصي إلى ملف .sh أيضًا، ولكن الاحتفاظ بالأشياء في العقدة يقلل من عبء الصيانة بالنسبة لي شخصيًا. في الماضي، في أي وقت كنت بحاجة إلى تحديث هذا الاسم المستعار، كنت سأضطر إلى لصقه في bash linter، وإجراء التغييرات، وتصغيره، ثم لصقه مرة أخرى في gitconfig الخاص بي. لقد كان هذا الأمر مؤلمًا، وكثيرًا ما كنت أتجنب تحديث الاسم المستعار بسبب ذلك. والآن بعد أن أصبح في ملف نصي، يمكنني تحديثه مثل أي برنامج نصي آخر.
بعض التحذيرات
عند إعداد الأسماء المستعارة مثل هذا، من المهم أن تتذكر أن cwd الخاص بالبرنامج النصي سيكون دليل العمل الحالي للقذيفة التي تقوم بتشغيل البرنامج النصي. سيتم التعامل مع أي مسارات ملفات نسبية في البرنامج النصي على أنها نسبة إلى cwd الخاص بالصدفة، وليس موقع البرنامج النصي. وهذا مفيد جدًا في بعض الأحيان، ومؤلم جدًا في أحيان أخرى. بالنسبة لبرنامجنا النصي الأساسي لإعادة الأساس، لا يمثل هذا مشكلة، والإشارة الوحيدة إلى حدوث ذلك هي أننا استخدمنا ~ في مسار الملف للإشارة إلى موقع البرنامج النصي كمسار مطلق.
قد يؤدي إدخال البرمجة النصية في الأسماء المستعارة لـ git أيضًا إلى إغراء إضافة المزيد والمزيد من المنطق إلى الأسماء المستعارة الخاصة بك. وقد يؤدي ذلك إلى صعوبة صيانتها وفهمها، ولكن أيضًا صعوبة تذكرها. لا يستحق الأمر الاحتفاظ باسم مستعار معقد للغاية، لأنك ستقل احتمالية استخدامه على أي حال. بالإضافة إلى ذلك، يجب أن تكون حريصًا على عدم إدخال أي شيء قد يستغرق وقتًا طويلاً حتى يصل إلى الأسماء المستعارة الخاصة بك. إذا كنت تقوم بتشغيل برنامج نصي يستغرق وقتًا طويلاً للتشغيل، فقد تحتاج إلى التفكير فيما إذا كان هذا هو المكان المناسب له.
خاتمة
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3