הי צפריר, אכן שאלה מעניינת. קח בחשבון שהhash כולל בתהליך החישוב שלו גם את ה-timestamp של הקומיט, כך שגם אם תמצא commit message שעונה על התנאי, לא תוכל לשחזר את התוצאה בריצה מאוחרת יותר. מכיוון שאתה לא משנה את ה tree אלא רק את הודעת הקומיט עצמו, יתכן שתוכל לחשב את ה hash מבלי ליצור קומיט של ממש באמצעות git hash-object או פקודה דומה. לפרטים נוספים על איך המימוש הפנימי של כל האובייקטים עובד, ממליץ על הפרק הבא: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
On Tue, 19 Feb 2019 at 13:56, Tzafrir Cohen <tzaf...@cohens.org.il> wrote: > שלום, > > > השאלה שלי סוטה מהכיוון הכללי של הרשימה הזו בזמן האחרון ולמרבה הפליאה לא > קשורה לאף ידיעה ב־ynet. > > > אני מנסה לעשות משהו קצת דבילי: יש לי מאגר גיט קטן ואני מנסה לדאוג שה־hash > של ה־commit האחרון יהיה מה שבחרתי. ליתר דיוק: הגרסה המקוצרת שלו: מכיוון > שזהו מאגר קטן, מדובר על המינימום: שבעה תווי hex. כלומר: 16^7או 2^28. זה > כבר בתחום המעשי. > > > התחלתי מהסקריפט הבא: > > #!/bin/bash > > target="f00ba11" > > max=$((16 ** 7)) > > commit_str() { > git show -s --'pretty=tformat:%h' HEAD > } > > commit_template="commit message title > > Try ____ > > " > > for i in `seq $max`; do > > if [ `commit_str` = "$target" ]; then > > break > > fi > > commit_msg=${commit_template/____/$i} > > git commit --amend -m "$commit_msg" > > echo -n "." > > done > > > הבעיה הראשונה הייתה לולאת ה־for ו־seq. הפלט שלו ענקי וזה מפוצץ את תהליך > באש עצמו (המכונה שלי הייתה קצת חנוקה עם זכרון). הפכתי את זה ללולאת for > רגילה יותר (לא היה לי כוח לבדוק אם לבאש יש משהו משלו): > > i=0 > while [ $i -lt $max ]; do > > if [ `commit_str` = "$target" ]; then > > break > > fi > > commit_msg=${commit_template/____/$i} > > git commit --amend -m "$commit_msg" > > echo -n "." > : $((i++)) > > done > > > > בשלב הזה ראיתי מהו הקצב, והחלטתי שהוא לא מספיק טוב ושאני יכול להריץ כמה > במקביל. העתקתי את התיקיה לעוד שלושה עותקים. לכל אחד שמתי קובץ בשם base_num, > בהתחלה קראתי את תוכנו למשתנה, ועכשיו שורת יצירת התבנית הפכה להיות: > > commit_msg=${commit_template/____/$base_num:$i} > > ואז שמתי לב שהאורך של ה־hash שמוצג לי כבר גדול מ־7. זה מוזר: נכון שאני > מייצר כל הזמן commit־ים לא מחוברים בכל הרצה של הלולאה, אבל מדי פעם רץ git > gc והוא אמור להיפטר מהם. ואז הבנתי שלא: > > 1. ה־reflog ממשיך להתייחס אליהם. > > 2. git gc מעיף אוטומטית רק commits בני שבועיים ויותר. > > > צריך להשתמש ב־git reflog expire: להגיד לו גם להתייחס לכל תוכן ה־log וגם > להפטר מכל מה שהוא מוצא, ולא רק מהישנים. את השינוי הבא לא להעתיק למקום אחר > אם אתם לא מבינים מה הוא עושה. > > באותה הזדמנות הוספתי גם קובץ בשם start שמוסיף את הערך שממנו צריך להתחיל > בפעם הבאה שמריצים (אם אני מפסיק באמצע). > > i=`cat start` > while [ $i -lt $max ]; do > > if [ `commit_str` = "$target" ]; then > > break > > fi > > commit_msg=${commit_template/____/$i} > > git commit --amend -m "$commit_msg" > case "$i" in *0000) > git reflog expire --all --expire=all > git gc --prune=all > echo $i >start > ;; > > esac > > echo -n "." > : $((i++)) > > done > > > לא מצאתי איך אפשר לעשות commit ללא עדכון ה־reflog. האם זה אפשרי? > > > וכן, אני מניח שזו לא הדרך היעילה ביותר לעשות את זה. הצעות לדרכים יעילות > יותר יתקבלו בברכה. > > > -- צפריר > _______________________________________________ > Discussions mailing list > Discussions@hamakor.org.il > http://hamakor.org.il/cgi-bin/mailman/listinfo/discussions -- יום טוב, תומר בריסקר
_______________________________________________ Discussions mailing list Discussions@hamakor.org.il http://hamakor.org.il/cgi-bin/mailman/listinfo/discussions