क्या मूल बनाने / संशोधित टाइमस्टैम्प को जानने या प्राप्त करने का कोई तरीका है?
क्या मूल बनाने / संशोधित टाइमस्टैम्प को जानने या प्राप्त करने का कोई तरीका है?
जवाबों:
मेरा मानना है कि Git डेटाबेस में दर्ज केवल टाइमस्टैम्प लेखक और प्रतिबद्ध टाइमस्टैम्प हैं। मुझे गइट के लिए फ़ाइल के टाइमस्टैम्प को संशोधित करने के लिए सबसे हालिया प्रतिबद्ध से मिलान करने का विकल्प नहीं दिखता है, और यह समझ में आता है कि यह डिफ़ॉल्ट व्यवहार नहीं होगा (क्योंकि यदि यह होता, तो मेकफाइल्स सही तरीके से काम नहीं करता)।
आप अपनी फ़ाइलों के संशोधन की तारीख को सबसे हाल के समय के लिए निर्धारित करने के लिए एक स्क्रिप्ट लिख सकते हैं। यह कुछ इस तरह लग सकता है:
IFS="
"
for FILE in $(git ls-files)
do
TIME=$(git log --pretty=format:%cd -n 1 --date=iso -- "$FILE")
TIME=$(date -j -f '%Y-%m-%d %H:%M:%S %z' "$TIME" +%Y%m%d%H%M.%S)
touch -m -t "$TIME" "$FILE"
done
YES , मेटास्टोर या git-cache-meta ऐसी (मेटा-) जानकारी स्टोर कर सकता है! थर्ड पार्टी टूल्स के बिना, अपने आप से गेट करें। Metastore या git-cache-meta किसी फ़ाइल के लिए कोई फ़ाइल मेटाडेटा संग्रहीत कर सकता है।
यह डिज़ाइन द्वारा है, जैसा कि मेटास्टोर या गिट-कैश-मेटा उस उद्देश्य के लिए है, साथ ही साथ बैकअप उपयोगिताओं और सिंक्रनाइज़ेशन टूल का समर्थन भी करता है।
(जकूब के जवाब पर थोड़ा सा मज़ेदार स्पिन क्षमा करें)
findके -printfएक्सटेंशन पर निर्भर करता है , और मैं लगभग निश्चित हूं कि metastore (C प्रोजेक्ट होने के नाते) पोर्टेबल बनाने के लिए और भी अधिक काम है। काफी दुर्भाग्यपूर्ण है। अगर मुझे पता चलता है कि यह स्थिति बदलती है तो मैं यहां वापस पोस्ट करूंगा।
नहीं , Git बस ऐसी (मेटा-) जानकारी को संग्रहीत नहीं करता है , जब तक कि आप तीसरे पक्ष के उपकरण जैसे मेटास्टोर या गिट-कैश-मेटा का उपयोग नहीं करते हैं। एकमात्र टाइमस्टैम्प जो संग्रहित होता है वह है समय पैच / परिवर्तन (लेखक समय) बनाया गया था, और समय कमिट किया गया था (कमेंट टाइम)।
यह डिज़ाइन द्वारा है, क्योंकि Git संस्करण नियंत्रण प्रणाली है, न कि बैकअप उपयोगिता या सिंक्रोनाइज़ेशन टूल।
अद्यतन : TL; DR: git अपने आप में मूल समय नहीं बचाता है, लेकिन कुछ समाधान विभिन्न तरीकों से इसे रोकते हैं। git-restore-mtimeउनमें से एक है:
https://github.com/MestreLion/git-tools/
उबंटू / डेबियन: sudo apt install git-restore-mtime
फेडोरा / आरएचईएल / सेंटोस:sudo yum install git-tools
देखें मेरे अन्य जवाब अधिक जानकारी के लिए
पूर्ण अस्वीकरण: मैं लेखक हूं git-tools
यह पाइथन स्क्रिप्ट मदद कर सकती है: प्रत्येक फ़ाइल के लिए सबसे हाल की प्रतिबद्ध समय-सीमा लागू होती है, जहाँ फ़ाइल को संशोधित किया गया था:
नीचे स्क्रिप्ट का वास्तव में नंगे हड्डियों वाला संस्करण है। वास्तविक उपयोग के लिए मैं ऊपर दिए गए अधिक मजबूत संस्करणों में से एक का सुझाव देता हूं:
#!/usr/bin/env python
# Bare-bones version. Current dir must be top-level of work tree.
# Usage: git-restore-mtime-bare [pathspecs...]
# By default update all files
# Example: to only update only the README and files in ./doc:
# git-restore-mtime-bare README doc
import subprocess, shlex
import sys, os.path
filelist = set()
for path in (sys.argv[1:] or [os.path.curdir]):
if os.path.isfile(path) or os.path.islink(path):
filelist.add(os.path.relpath(path))
elif os.path.isdir(path):
for root, subdirs, files in os.walk(path):
if '.git' in subdirs:
subdirs.remove('.git')
for file in files:
filelist.add(os.path.relpath(os.path.join(root, file)))
mtime = 0
gitobj = subprocess.Popen(shlex.split('git whatchanged --pretty=%at'),
stdout=subprocess.PIPE)
for line in gitobj.stdout:
line = line.strip()
if not line: continue
if line.startswith(':'):
file = line.split('\t')[-1]
if file in filelist:
filelist.remove(file)
#print mtime, file
os.utime(file, (mtime, mtime))
else:
mtime = long(line)
# All files done?
if not filelist:
break
सभी संस्करण एकल git whatchangedकमांड द्वारा उत्पन्न पूर्ण लॉग को पार्स करते हैं , जो कि प्रत्येक फ़ाइल के लिए लूपिंग की तुलना में सैकड़ों गुना तेज है। Git के लिए 4 सेकंड के तहत (24,000 कमिट, 2,500 फाइलें) और लिनक्स कर्नेल के लिए 1 मिनट से कम (40,000 फाइलें, 300,000 कमिट)
$ python ./git-restore-mtime Traceback (most recent call last): File "./git-restore-mtime", line 122, in <module> 'git rev-parse --show-toplevel --git-dir')).split('\n')[:2] TypeError: Type str doesn't support the buffer APIक्या आप शायद यह बताएंगे कि पायथन के किस संस्करण की आवश्यकता है? मैं 3.3.3 का उपयोग कर रहा हूँ
strपायथन 2 bytestringमें पायथन 3 के बराबर है , जबकि strपायथन 3 unicodeमें पायथन 2 में है। क्या आप इस मुद्दे को github.com/MestreLion/git-tools/issues पर रिपोर्ट कर सकते हैं ?
मैं कुछ समय पहले से ही git और फ़ाइल टाइमस्टैम्प के साथ झड़प कर रहा हूँ।
आपके कुछ विचारों का परीक्षण किया और मेरा अपना बना हुआ विशाल और पूर्ववर्ती / राम भारी लिपियों, अनफिल आई (कुछ गित विकी पर) पर्ल में एक स्क्रिप्ट मिली जो लगभग वही करता है जो मैं चाहता था। https://git.wiki.kernel.org/index.php/ExampleScripts
और जो मैं चाहता था वह प्रतिबद्ध तारीखों के आधार पर फाइलों के अंतिम संशोधन को संरक्षित करने में सक्षम होना चाहिए।
इसलिए कुछ पुनरावृत्ति के बाद स्क्रिप्ट लगभग 2-3min में 200k फ़ाइलों के निर्माण और संशोधन की तारीख को बदलने में सक्षम है ।
#!/usr/bin/perl
my %attributions;
my $remaining = 0;
open IN, "git ls-tree -r --full-name HEAD |" or die;
while (<IN>) {
if (/^\S+\s+blob \S+\s+(\S+)$/) {
$attributions{$1} = -1;
}
}
close IN;
$remaining = (keys %attributions) + 1;
print "Number of files: $remaining\n";
open IN, "git log -r --root --raw --no-abbrev --date=raw --pretty=format:%h~%cd~ |" or die;
while (<IN>) {
if (/^([^:~]+)~([^~]+)~$/) {
($commit, $date) = ($1, $2);
} elsif (/^:\S+\s+1\S+\s+\S+\s+\S+\s+\S\s+(.*)$/) {
if ($attributions{$1} == -1) {
$attributions{$1} = "$date";
$remaining--;
utime $date, $date, $1;
if ($remaining % 1000 == 0) {
print "$remaining\n";
}
if ($remaining <= 0) {
break;
}
}
}
}
close IN;
यह मानते हुए कि आपकी रिपॉजिटरी के पास 10k + फाइलें नहीं हैं, जिसे निष्पादित करने के लिए सेकंड चाहिए, इसलिए आप इसे चेकआउट, हुक या अन्य गिट बेसिक हुक को हुक कर सकते हैं।
यहाँ मेरा समाधान है कि रिक्त स्थान पर विचार पथ में ले जाता है:
#! /bin/bash
IFS=$'\n'
list_of_files=($(git ls-files | sort))
unset IFS
for file in "${list_of_files[@]}"; do
file_name=$(echo $file)
## When you collect the timestamps:
TIME=$(date -r "$file_name" -Ins)
## When you want to recover back the timestamps:
touch -m -d $TIME "$file_name"
done
ध्यान दें कि यह समय नहीं लेता है जो git logरिपोर्ट करता है, यह सिस्टम द्वारा रिपोर्ट किया गया समय है। यदि आप समय चाहते हैं क्योंकि फाइलों को शुरू किया गया था, तो git logइसके बजाय समाधान का उपयोग करेंdate -r
नेटिव git में कार्यक्षमता नहीं है, लेकिन इसे हुक स्क्रिप्ट या थर्ड पार्टी टूल्स द्वारा प्राप्त किया जा सकता है।
मैंने कोशिश की है metastore। यह बहुत तेज़ है, लेकिन मुझे स्थापित करने की आवश्यकता नहीं है और यह कि मेटाडेटा सादे पाठ प्रारूप में संग्रहीत नहीं है। git-cache-metaएक सरल उपकरण है जो मैंने कोशिश की है, लेकिन यह बड़े रिपोज (दसियों हजारों फाइलों के साथ रेपो के लिए, यह मेटाडेटा फ़ाइल को अपडेट करने में मिनटों का समय लेता है) के लिए बेहद धीमा है और इसमें क्रॉस-प्लेटफॉर्म संगतता समस्याएं हो सकती हैं। setgitpermsऔर अन्य दृष्टिकोणों में भी उनकी कमियाँ हैं जो मुझे पसंद नहीं हैं।
अंत में मैंने इस काम के लिए एक हुक स्क्रिप्ट बनाई: git-store-meta । इसकी बहुत हल्की निर्भरता है (* निक्स शेल, sortऔर perl, जिसे गिट की आवश्यकता होती है, और वैकल्पिक रूप से chown, chgrpऔर touch) ताकि अतिरिक्त कुछ भी एक प्लेटफ़ॉर्म के लिए स्थापित न हो जो कि चलाए जा सके, वांछनीय प्रदर्शन (दसियों के साथ रेपो के लिए) फ़ाइलों का, मेटाडेटा फ़ाइल को अपडेट करने के लिए <10 सेकंड लगते हैं; हालांकि अब बनाने के लिए), सादे पाठ प्रारूप में डेटा बचाता है , और जो मेटाडेटा "बचाया" या "लोड" होने के लिए अनुकूलन योग्य है ।
इसने मेरे लिए ठीक काम किया है। यदि आप मेटास्टोर, गिट-कैश-मेटा, और अन्य तरीकों से संतुष्ट नहीं हैं, तो यह कोशिश करें।
मुझे आशा है कि आप सादगी की सराहना करेंगे:
# getcheckin - Retrieve the last committed checkin date and time for
# each of the files in the git project. After a "pull"
# of the project, you can update the timestamp on the
# pulled files to match that date/time. There are many
# that believe that this is not a good idea, but
# I found it useful to get the right source file dates
#
# NOTE: This script produces commands suitable for
# piping into BASH or other shell
# License: Creative Commons Attribution 3.0 United States
# (CC by 3.0 US)
##########
# walk back to the project parent or the relative pathnames don't make
# sense
##########
while [ ! -d ./.git ]
do
cd ..
done
echo "cd $(pwd)"
##########
# Note that the date format is ISO so that touch will work
##########
git ls-tree -r --full-tree HEAD |\
sed -e "s/.*\t//" | while read filename; do
echo "touch --date=\"$(git log -1 --date=iso --format="%ad" -- "$filename")\" -m $filename"
done
विंडोज पर्यावरण के लिए मैंने डेल्फी 10.1 बर्लिन में एक छोटा (त्वरित और गंदा) ईएक्सई लिखा है जो स्रोत ट्री में सभी फ़ाइल तिथियों को फ़ाइल में इकट्ठा करता है। .itfilattr और उन्हें चेक किए गए हमारे सोर्स ट्री पर फिर से लागू कर सकते हैं।
बेशक मैं GitHub में कोड साझा करता हूं:
https://github.com/michaschumann/gitfiledates/blob/master/gitFileDates.dpr
मैं इसे अपने बिल्ड सिस्टम में GitLab धावकों के आधार पर उपयोग करता हूं।
ओपी के बारे में मेरी (और अन्य ') व्याख्या में कुछ अस्पष्टता है कि इसका मतलब है कि प्रतिबद्ध समय या कुछ और, लेकिन यह मानते हुए कि इसका मतलब है कि प्रतिबद्ध समय है, तो यह सरल वन-लाइनर लिनक्स में काम करेगा (डिट्रिच एप के उत्तर स्निपेट के आधार पर) ):
git ls-files | xargs -I{} bash -c 'touch "{}" --date=@$(git log -n1 --pretty=format:%ct -- "{}")'
लेकिन वहाँ अधिक परिष्कृत उत्तर (git हुक सहित) एक टिप्पणी से मूल सवाल cregox द्वारा जुड़ा हुआ है।
--date=@foo
GNU टूल्स के साथ।
s=$(git ls-files | wc -l);
git ls-files -z |
xargs -0 -I{} -n1 bash -c \
"git log --date=format:%Y%m%d%H%M.%S '--pretty=format:touch -m -t %cd \"{}\"%n' -n1 -- {}"|
pv -l -s$s |
parallel -n1 -j8
967 0:00:05 [ 171 /s] [=====================================> ] 16%
।
$ git --version ; xargs --version | sed 1q ; ls --version | sed 1q;
parallel --version | sed 1q; pv --version | sed 1q; sh --version | sed 1q
git version 2.13.0
xargs (GNU findutils) 4.6.0
ls (GNU coreutils) 8.25
GNU parallel 20150522
pv 1.6.0 - Copyright 2015 Andrew Wood <andrew.wood@ivarch.com>
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
CentOS 7 में आपके पास /usr/share/doc/rsync-*/support/git-set-file-timesऔर डेबियन (और डेरिवेटिव) में एक ही स्क्रिप्ट है /usr/share/doc/rsync/scripts/git-set-file-times.gz, मूल एरिक वोंग से है और यहां https://yhbt.net/git-set-file-times है ।
यह यहां बताए गए अन्य उदाहरणों की तुलना में तेजी से काम करता है और आपको इसे अपने लिनक्स वितरण पर पहले से ही अधिक उपयोगी लग सकता है।
ये मेरा।
कुछ अन्य लोगों की तुलना में थोड़ा तेज, क्योंकि मैं प्रत्येक फ़ाइल के लिए 'गेट लॉग' नहीं कह रहा हूँ; इसके बजाय, 'git log' को एक बार कॉल करना और उस आउटपुट को टच कमांड में बदलना।
ऐसे मामले होंगे जहां 1 शेल कमांड बफ़र में फिट होने के लिए 1 प्रतिबद्ध में बहुत अधिक सूचीबद्ध फाइलें हैं; बाइट्स में एक कमांड की अधिकतम लंबाई देखने के लिए "getconf ARG_MAX" चलाएं - मेरे डेबियन इंस्टॉल पर, यह 2 एमबी है, जो बहुत है।
# set file last modification time to last commit of file
git log --reverse --date=iso --name-only | \
grep -vE "^(commit |Merge:|Author:| |^$)" | \
grep -B 1 "^[^D][^a][^t][^e][^:][^ ]" | \
grep -v "^\-\-" | \
sed "s|^\(.*\)$|\"\1\"|;s|^\"Date: *\(.*\)\"$|~touch -c -m -d'\1'|" | \
tr '~\n' '\n ' | \
sh -
लाइन द्वारा विवरण:
गति के संदर्भ में, यह 700 सेकंड में 6500 फाइलों के लिए 5 सेकंड 1700 का है।